#include "dataproc.h"

/******************************************************************************
 * name:    crc-4/itu           x4+x+1
 * poly:    0x03
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc4itu_table[256] = {
    0x00, 0x07, 0x0e, 0x09, 0x05, 0x02, 0x0b, 0x0c, 0x0a, 0x0d, 0x04, 0x03, 0x0f, 0x08, 0x01, 0x06,
    0x0d, 0x0a, 0x03, 0x04, 0x08, 0x0f, 0x06, 0x01, 0x07, 0x00, 0x09, 0x0e, 0x02, 0x05, 0x0c, 0x0b,
    0x03, 0x04, 0x0d, 0x0a, 0x06, 0x01, 0x08, 0x0f, 0x09, 0x0e, 0x07, 0x00, 0x0c, 0x0b, 0x02, 0x05,
    0x0e, 0x09, 0x00, 0x07, 0x0b, 0x0c, 0x05, 0x02, 0x04, 0x03, 0x0a, 0x0d, 0x01, 0x06, 0x0f, 0x08,
    0x06, 0x01, 0x08, 0x0f, 0x03, 0x04, 0x0d, 0x0a, 0x0c, 0x0b, 0x02, 0x05, 0x09, 0x0e, 0x07, 0x00,
    0x0b, 0x0c, 0x05, 0x02, 0x0e, 0x09, 0x00, 0x07, 0x01, 0x06, 0x0f, 0x08, 0x04, 0x03, 0x0a, 0x0d,
    0x05, 0x02, 0x0b, 0x0c, 0x00, 0x07, 0x0e, 0x09, 0x0f, 0x08, 0x01, 0x06, 0x0a, 0x0d, 0x04, 0x03,
    0x08, 0x0f, 0x06, 0x01, 0x0d, 0x0a, 0x03, 0x04, 0x02, 0x05, 0x0c, 0x0b, 0x07, 0x00, 0x09, 0x0e,
    0x0c, 0x0b, 0x02, 0x05, 0x09, 0x0e, 0x07, 0x00, 0x06, 0x01, 0x08, 0x0f, 0x03, 0x04, 0x0d, 0x0a,
    0x01, 0x06, 0x0f, 0x08, 0x04, 0x03, 0x0a, 0x0d, 0x0b, 0x0c, 0x05, 0x02, 0x0e, 0x09, 0x00, 0x07,
    0x0f, 0x08, 0x01, 0x06, 0x0a, 0x0d, 0x04, 0x03, 0x05, 0x02, 0x0b, 0x0c, 0x00, 0x07, 0x0e, 0x09,
    0x02, 0x05, 0x0c, 0x0b, 0x07, 0x00, 0x09, 0x0e, 0x08, 0x0f, 0x06, 0x01, 0x0d, 0x0a, 0x03, 0x04,
    0x0a, 0x0d, 0x04, 0x03, 0x0f, 0x08, 0x01, 0x06, 0x00, 0x07, 0x0e, 0x09, 0x05, 0x02, 0x0b, 0x0c,
    0x07, 0x00, 0x09, 0x0e, 0x02, 0x05, 0x0c, 0x0b, 0x0d, 0x0a, 0x03, 0x04, 0x08, 0x0f, 0x06, 0x01,
    0x09, 0x0e, 0x07, 0x00, 0x0c, 0x0b, 0x02, 0x05, 0x03, 0x04, 0x0d, 0x0a, 0x06, 0x01, 0x08, 0x0f,
    0x04, 0x03, 0x0a, 0x0d, 0x01, 0x06, 0x0f, 0x08, 0x0e, 0x09, 0x00, 0x07, 0x0b, 0x0c, 0x05, 0x02,
};

uint8_t crc4_itu_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc4itu_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-4/itu           x4+x+1
 * note:    d for直接计算
 *****************************************************************************/
uint8_t crc4_itu_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        crc ^= *data++;                 // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x0c;// 0x0c = (reverse 0x03)>>(8-4)
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-5/epc           x5+x3+1
 * poly:    0x09
 * init:    0x09
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc5epu_table[256] = {
    0x00, 0x48, 0x90, 0xd8, 0x68, 0x20, 0xf8, 0xb0, 0xd0, 0x98, 0x40, 0x08, 0xb8, 0xf0, 0x28, 0x60,
    0xe8, 0xa0, 0x78, 0x30, 0x80, 0xc8, 0x10, 0x58, 0x38, 0x70, 0xa8, 0xe0, 0x50, 0x18, 0xc0, 0x88,
    0x98, 0xd0, 0x08, 0x40, 0xf0, 0xb8, 0x60, 0x28, 0x48, 0x00, 0xd8, 0x90, 0x20, 0x68, 0xb0, 0xf8,
    0x70, 0x38, 0xe0, 0xa8, 0x18, 0x50, 0x88, 0xc0, 0xa0, 0xe8, 0x30, 0x78, 0xc8, 0x80, 0x58, 0x10,
    0x78, 0x30, 0xe8, 0xa0, 0x10, 0x58, 0x80, 0xc8, 0xa8, 0xe0, 0x38, 0x70, 0xc0, 0x88, 0x50, 0x18,
    0x90, 0xd8, 0x00, 0x48, 0xf8, 0xb0, 0x68, 0x20, 0x40, 0x08, 0xd0, 0x98, 0x28, 0x60, 0xb8, 0xf0,
    0xe0, 0xa8, 0x70, 0x38, 0x88, 0xc0, 0x18, 0x50, 0x30, 0x78, 0xa0, 0xe8, 0x58, 0x10, 0xc8, 0x80,
    0x08, 0x40, 0x98, 0xd0, 0x60, 0x28, 0xf0, 0xb8, 0xd8, 0x90, 0x48, 0x00, 0xb0, 0xf8, 0x20, 0x68,
    0xf0, 0xb8, 0x60, 0x28, 0x98, 0xd0, 0x08, 0x40, 0x20, 0x68, 0xb0, 0xf8, 0x48, 0x00, 0xd8, 0x90,
    0x18, 0x50, 0x88, 0xc0, 0x70, 0x38, 0xe0, 0xa8, 0xc8, 0x80, 0x58, 0x10, 0xa0, 0xe8, 0x30, 0x78,
    0x68, 0x20, 0xf8, 0xb0, 0x00, 0x48, 0x90, 0xd8, 0xb8, 0xf0, 0x28, 0x60, 0xd0, 0x98, 0x40, 0x08,
    0x80, 0xc8, 0x10, 0x58, 0xe8, 0xa0, 0x78, 0x30, 0x50, 0x18, 0xc0, 0x88, 0x38, 0x70, 0xa8, 0xe0,
    0x88, 0xc0, 0x18, 0x50, 0xe0, 0xa8, 0x70, 0x38, 0x58, 0x10, 0xc8, 0x80, 0x30, 0x78, 0xa0, 0xe8,
    0x60, 0x28, 0xf0, 0xb8, 0x08, 0x40, 0x98, 0xd0, 0xb0, 0xf8, 0x20, 0x68, 0xd8, 0x90, 0x48, 0x00,
    0x10, 0x58, 0x80, 0xc8, 0x78, 0x30, 0xe8, 0xa0, 0xc0, 0x88, 0x50, 0x18, 0xa8, 0xe0, 0x38, 0x70,
    0xf8, 0xb0, 0x68, 0x20, 0x90, 0xd8, 0x00, 0x48, 0x28, 0x60, 0xb8, 0xf0, 0x40, 0x08, 0xd0, 0x98,
};

uint8_t crc5_epc_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0x48;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ (*data++);
        crc = crc5epu_table[tmp];
    }
    return crc >> 3;
}
/*
 * name:    crc-5/epc           x5+x3+1
 * note:    d for直接计算
 */
uint8_t crc5_epc_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0x48;        // initial value: 0x48 = 0x09<<(8-5)
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x48;        // 0x48 = 0x09<<(8-5)
            else
                crc <<= 1;
        }
    }
    return crc >> 3;
}
/******************************************************************************
 * name:    crc-5/itu           x5+x4+x2+1
 * poly:    0x15
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * note:
 *****************************************************************************/

const static uint8_t crc5itu_table[256] = {
    0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x13, 0x14, 0x1d, 0x1a, 0x0f, 0x08, 0x01, 0x06,
    0x0d, 0x0a, 0x03, 0x04, 0x11, 0x16, 0x1f, 0x18, 0x1e, 0x19, 0x10, 0x17, 0x02, 0x05, 0x0c, 0x0b,
    0x1a, 0x1d, 0x14, 0x13, 0x06, 0x01, 0x08, 0x0f, 0x09, 0x0e, 0x07, 0x00, 0x15, 0x12, 0x1b, 0x1c,
    0x17, 0x10, 0x19, 0x1e, 0x0b, 0x0c, 0x05, 0x02, 0x04, 0x03, 0x0a, 0x0d, 0x18, 0x1f, 0x16, 0x11,
    0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 0x0c, 0x0b, 0x02, 0x05, 0x10, 0x17, 0x1e, 0x19,
    0x12, 0x15, 0x1c, 0x1b, 0x0e, 0x09, 0x00, 0x07, 0x01, 0x06, 0x0f, 0x08, 0x1d, 0x1a, 0x13, 0x14,
    0x05, 0x02, 0x0b, 0x0c, 0x19, 0x1e, 0x17, 0x10, 0x16, 0x11, 0x18, 0x1f, 0x0a, 0x0d, 0x04, 0x03,
    0x08, 0x0f, 0x06, 0x01, 0x14, 0x13, 0x1a, 0x1d, 0x1b, 0x1c, 0x15, 0x12, 0x07, 0x00, 0x09, 0x0e,
    0x15, 0x12, 0x1b, 0x1c, 0x09, 0x0e, 0x07, 0x00, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
    0x18, 0x1f, 0x16, 0x11, 0x04, 0x03, 0x0a, 0x0d, 0x0b, 0x0c, 0x05, 0x02, 0x17, 0x10, 0x19, 0x1e,
    0x0f, 0x08, 0x01, 0x06, 0x13, 0x14, 0x1d, 0x1a, 0x1c, 0x1b, 0x12, 0x15, 0x00, 0x07, 0x0e, 0x09,
    0x02, 0x05, 0x0c, 0x0b, 0x1e, 0x19, 0x10, 0x17, 0x11, 0x16, 0x1f, 0x18, 0x0d, 0x0a, 0x03, 0x04,
    0x0a, 0x0d, 0x04, 0x03, 0x16, 0x11, 0x18, 0x1f, 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c,
    0x07, 0x00, 0x09, 0x0e, 0x1b, 0x1c, 0x15, 0x12, 0x14, 0x13, 0x1a, 0x1d, 0x08, 0x0f, 0x06, 0x01,
    0x10, 0x17, 0x1e, 0x19, 0x0c, 0x0b, 0x02, 0x05, 0x03, 0x04, 0x0d, 0x0a, 0x1f, 0x18, 0x11, 0x16,
    0x1d, 0x1a, 0x13, 0x14, 0x01, 0x06, 0x0f, 0x08, 0x0e, 0x09, 0x00, 0x07, 0x12, 0x15, 0x1c, 0x1b,
};

uint8_t crc5_itu_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc5itu_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-5/itu           x5+x4+x2+1
 * note:    d for直接计算
 *****************************************************************************/

uint8_t crc5_itu_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        crc ^= *data++;                 // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x15;// 0x15 = (reverse 0x15)>>(8-5)
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-5/usb           x5+x2+1
 * poly:    0x05
 * init:    0x1f
 * refin:   true
 * refout:  true
 * xorout:  0x1f
 * note:
 *****************************************************************************/
const static uint8_t crc5usb_table[256] = {
    0x00, 0x0e, 0x1c, 0x12, 0x11, 0x1f, 0x0d, 0x03, 0x0b, 0x05, 0x17, 0x19, 0x1a, 0x14, 0x06, 0x08,
    0x16, 0x18, 0x0a, 0x04, 0x07, 0x09, 0x1b, 0x15, 0x1d, 0x13, 0x01, 0x0f, 0x0c, 0x02, 0x10, 0x1e,
    0x05, 0x0b, 0x19, 0x17, 0x14, 0x1a, 0x08, 0x06, 0x0e, 0x00, 0x12, 0x1c, 0x1f, 0x11, 0x03, 0x0d,
    0x13, 0x1d, 0x0f, 0x01, 0x02, 0x0c, 0x1e, 0x10, 0x18, 0x16, 0x04, 0x0a, 0x09, 0x07, 0x15, 0x1b,
    0x0a, 0x04, 0x16, 0x18, 0x1b, 0x15, 0x07, 0x09, 0x01, 0x0f, 0x1d, 0x13, 0x10, 0x1e, 0x0c, 0x02,
    0x1c, 0x12, 0x00, 0x0e, 0x0d, 0x03, 0x11, 0x1f, 0x17, 0x19, 0x0b, 0x05, 0x06, 0x08, 0x1a, 0x14,
    0x0f, 0x01, 0x13, 0x1d, 0x1e, 0x10, 0x02, 0x0c, 0x04, 0x0a, 0x18, 0x16, 0x15, 0x1b, 0x09, 0x07,
    0x19, 0x17, 0x05, 0x0b, 0x08, 0x06, 0x14, 0x1a, 0x12, 0x1c, 0x0e, 0x00, 0x03, 0x0d, 0x1f, 0x11,
    0x14, 0x1a, 0x08, 0x06, 0x05, 0x0b, 0x19, 0x17, 0x1f, 0x11, 0x03, 0x0d, 0x0e, 0x00, 0x12, 0x1c,
    0x02, 0x0c, 0x1e, 0x10, 0x13, 0x1d, 0x0f, 0x01, 0x09, 0x07, 0x15, 0x1b, 0x18, 0x16, 0x04, 0x0a,
    0x11, 0x1f, 0x0d, 0x03, 0x00, 0x0e, 0x1c, 0x12, 0x1a, 0x14, 0x06, 0x08, 0x0b, 0x05, 0x17, 0x19,
    0x07, 0x09, 0x1b, 0x15, 0x16, 0x18, 0x0a, 0x04, 0x0c, 0x02, 0x10, 0x1e, 0x1d, 0x13, 0x01, 0x0f,
    0x1e, 0x10, 0x02, 0x0c, 0x0f, 0x01, 0x13, 0x1d, 0x15, 0x1b, 0x09, 0x07, 0x04, 0x0a, 0x18, 0x16,
    0x08, 0x06, 0x14, 0x1a, 0x19, 0x17, 0x05, 0x0b, 0x03, 0x0d, 0x1f, 0x11, 0x12, 0x1c, 0x0e, 0x00,
    0x1b, 0x15, 0x07, 0x09, 0x0a, 0x04, 0x16, 0x18, 0x10, 0x1e, 0x0c, 0x02, 0x01, 0x0f, 0x1d, 0x13,
    0x0d, 0x03, 0x11, 0x1f, 0x1c, 0x12, 0x00, 0x0e, 0x06, 0x08, 0x1a, 0x14, 0x17, 0x19, 0x0b, 0x05,
};

/* crc5_usb_calc */
uint8_t crc5_usb_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0x1f;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc5usb_table[tmp];
    }
    return crc ^ 0x1f;
}

/*
 * name:    crc-5/usb           x5+x2+1
 * note:    d for直接计算
 */
uint8_t crc5_usb_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0x1f;                // initial value
    while (length--)
    {
        crc ^= *data++;                 // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x14;// 0x14 = (reverse 0x05)>>(8-5)
            else
                crc = (crc >> 1);
        }
    }
    return crc ^ 0x1f;
}
/******************************************************************************
 * name:    crc-6/itu           x6+x+1
 * poly:    0x03
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc6itu_table[256] = {
    0x00, 0x14, 0x28, 0x3c, 0x31, 0x25, 0x19, 0x0d, 0x03, 0x17, 0x2b, 0x3f, 0x32, 0x26, 0x1a, 0x0e,
    0x06, 0x12, 0x2e, 0x3a, 0x37, 0x23, 0x1f, 0x0b, 0x05, 0x11, 0x2d, 0x39, 0x34, 0x20, 0x1c, 0x08,
    0x0c, 0x18, 0x24, 0x30, 0x3d, 0x29, 0x15, 0x01, 0x0f, 0x1b, 0x27, 0x33, 0x3e, 0x2a, 0x16, 0x02,
    0x0a, 0x1e, 0x22, 0x36, 0x3b, 0x2f, 0x13, 0x07, 0x09, 0x1d, 0x21, 0x35, 0x38, 0x2c, 0x10, 0x04,
    0x18, 0x0c, 0x30, 0x24, 0x29, 0x3d, 0x01, 0x15, 0x1b, 0x0f, 0x33, 0x27, 0x2a, 0x3e, 0x02, 0x16,
    0x1e, 0x0a, 0x36, 0x22, 0x2f, 0x3b, 0x07, 0x13, 0x1d, 0x09, 0x35, 0x21, 0x2c, 0x38, 0x04, 0x10,
    0x14, 0x00, 0x3c, 0x28, 0x25, 0x31, 0x0d, 0x19, 0x17, 0x03, 0x3f, 0x2b, 0x26, 0x32, 0x0e, 0x1a,
    0x12, 0x06, 0x3a, 0x2e, 0x23, 0x37, 0x0b, 0x1f, 0x11, 0x05, 0x39, 0x2d, 0x20, 0x34, 0x08, 0x1c,
    0x30, 0x24, 0x18, 0x0c, 0x01, 0x15, 0x29, 0x3d, 0x33, 0x27, 0x1b, 0x0f, 0x02, 0x16, 0x2a, 0x3e,
    0x36, 0x22, 0x1e, 0x0a, 0x07, 0x13, 0x2f, 0x3b, 0x35, 0x21, 0x1d, 0x09, 0x04, 0x10, 0x2c, 0x38,
    0x3c, 0x28, 0x14, 0x00, 0x0d, 0x19, 0x25, 0x31, 0x3f, 0x2b, 0x17, 0x03, 0x0e, 0x1a, 0x26, 0x32,
    0x3a, 0x2e, 0x12, 0x06, 0x0b, 0x1f, 0x23, 0x37, 0x39, 0x2d, 0x11, 0x05, 0x08, 0x1c, 0x20, 0x34,
    0x28, 0x3c, 0x00, 0x14, 0x19, 0x0d, 0x31, 0x25, 0x2b, 0x3f, 0x03, 0x17, 0x1a, 0x0e, 0x32, 0x26,
    0x2e, 0x3a, 0x06, 0x12, 0x1f, 0x0b, 0x37, 0x23, 0x2d, 0x39, 0x05, 0x11, 0x1c, 0x08, 0x34, 0x20,
    0x24, 0x30, 0x0c, 0x18, 0x15, 0x01, 0x3d, 0x29, 0x27, 0x33, 0x0f, 0x1b, 0x16, 0x02, 0x3e, 0x2a,
    0x22, 0x36, 0x0a, 0x1e, 0x13, 0x07, 0x3b, 0x2f, 0x21, 0x35, 0x09, 0x1d, 0x10, 0x04, 0x38, 0x2c,
};

uint8_t crc6_itu_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc6itu_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-6/itu           x6+x+1
 * note:    d for直接计算
 *****************************************************************************/

uint8_t crc6_itu_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;         // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x30;// 0x30 = (reverse 0x03)>>(8-6)
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-7/mmc           x7+x3+1
 * poly:    0x09
 * init:    0x00
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * use:     multimediacard,sd,ect.
 *****************************************************************************/
const static uint8_t crc7mmc_table[256] = {
    0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee,
    0x32, 0x20, 0x16, 0x04, 0x7a, 0x68, 0x5e, 0x4c, 0xa2, 0xb0, 0x86, 0x94, 0xea, 0xf8, 0xce, 0xdc,
    0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a,
    0x56, 0x44, 0x72, 0x60, 0x1e, 0x0c, 0x3a, 0x28, 0xc6, 0xd4, 0xe2, 0xf0, 0x8e, 0x9c, 0xaa, 0xb8,
    0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26,
    0xfa, 0xe8, 0xde, 0xcc, 0xb2, 0xa0, 0x96, 0x84, 0x6a, 0x78, 0x4e, 0x5c, 0x22, 0x30, 0x06, 0x14,
    0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, 0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42,
    0x9e, 0x8c, 0xba, 0xa8, 0xd6, 0xc4, 0xf2, 0xe0, 0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62, 0x70,
    0x82, 0x90, 0xa6, 0xb4, 0xca, 0xd8, 0xee, 0xfc, 0x12, 0x00, 0x36, 0x24, 0x5a, 0x48, 0x7e, 0x6c,
    0xb0, 0xa2, 0x94, 0x86, 0xf8, 0xea, 0xdc, 0xce, 0x20, 0x32, 0x04, 0x16, 0x68, 0x7a, 0x4c, 0x5e,
    0xe6, 0xf4, 0xc2, 0xd0, 0xae, 0xbc, 0x8a, 0x98, 0x76, 0x64, 0x52, 0x40, 0x3e, 0x2c, 0x1a, 0x08,
    0xd4, 0xc6, 0xf0, 0xe2, 0x9c, 0x8e, 0xb8, 0xaa, 0x44, 0x56, 0x60, 0x72, 0x0c, 0x1e, 0x28, 0x3a,
    0x4a, 0x58, 0x6e, 0x7c, 0x02, 0x10, 0x26, 0x34, 0xda, 0xc8, 0xfe, 0xec, 0x92, 0x80, 0xb6, 0xa4,
    0x78, 0x6a, 0x5c, 0x4e, 0x30, 0x22, 0x14, 0x06, 0xe8, 0xfa, 0xcc, 0xde, 0xa0, 0xb2, 0x84, 0x96,
    0x2e, 0x3c, 0x0a, 0x18, 0x66, 0x74, 0x42, 0x50, 0xbe, 0xac, 0x9a, 0x88, 0xf6, 0xe4, 0xd2, 0xc0,
    0x1c, 0x0e, 0x38, 0x2a, 0x54, 0x46, 0x70, 0x62, 0x8c, 0x9e, 0xa8, 0xba, 0xc4, 0xd6, 0xe0, 0xf2,
};

uint8_t crc7_mmc_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc7mmc_table[tmp];
    }
    return crc >> 1;
}


/*
 * name:    crc-7/mmc           x7+x3+1
 * note:    d for直接计算
 */
uint8_t crc7_mmc_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x12;        // 0x12 = 0x09<<(8-7)
            else
                crc <<= 1;
        }
    }
    return crc >> 1;
}


/******************************************************************************
 * name:    crc-8               x8+x2+x+1
 * poly:    0x07
 * init:    0x00
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/

const static uint8_t crc8_table[256] = {
    0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d,
    0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d,
    0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
    0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd,
    0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea,
    0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
    0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a,
    0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a,
    0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
    0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4,
    0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44,
    0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
    0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63,
    0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13,
    0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
    0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3,
};

/* crc8_calc */
uint8_t crc8_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc8_table[tmp];
    }
    return crc;
}

/*
 * name:    crc-8               x8+x2+x+1
 * note:    d for 直接计算
 */
uint8_t crc8_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x07;
            else
                crc <<= 1;
        }
    }
    return crc;
}

/******************************************************************************
 * name:    crc-8/itu           x8+x2+x+1
 * poly:    0x07
 * init:    0x00
 * refin:   false
 * refout:  false
 * xorout:  0x55
 * alias:   crc-8/atm
 *****************************************************************************/

uint8_t crc8_itu_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;      // crc ^= *data; data++;
        crc = crc8_table[tmp];    // 与crc8_table表格一致
    }
    return crc ^ 0x55;
}
/******************************************************************************
 * name:    crc-8/itu           x8+x2+x+1
 * note:    d for直接计算
 *****************************************************************************/

uint8_t crc8_itu_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x07;
            else
                crc <<= 1;
        }
    }
    return crc ^ 0x55;
}

/******************************************************************************
 * name:    crc-8/rohc          x8+x2+x+1
 * poly:    0x07
 * init:    0xff
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc8rohc_table[256] = {
    0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b,
    0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67,
    0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43,
    0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f,
    0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b,
    0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17,
    0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33,
    0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f,
    0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b,
    0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87,
    0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3,
    0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf,
    0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb,
    0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7,
    0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3,
    0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf,
};

/* crc8_calc */
uint8_t crc8_rohc_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0xff;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc8rohc_table[tmp];
    }
    return crc;
}
/*
 * name:    crc-8/rohc          x8+x2+x+1
 * note:    d for直接计算
 */
uint8_t crc8_rohc_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0xff;         // initial value
    while (length--)
    {
        crc ^= *data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xe0; // 0xe0 = reverse 0x07
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/maxim         x8+x5+x4+1
 * poly:    0x31
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * alias:   dow-crc,crc-8/ibutton
 * use:     maxim(dallas)'s some devices,e.g. ds18b20
 *****************************************************************************/
const static uint8_t crc8maxim_table[256] = {
    0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83, 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
    0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e, 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
    0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0, 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
    0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d, 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
    0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5, 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
    0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58, 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
    0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6, 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
    0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b, 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
    0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f, 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
    0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92, 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
    0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c, 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
    0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1, 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
    0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49, 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
    0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4, 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
    0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a, 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
    0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7, 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35,
};

uint8_t crc8_maxim_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc8maxim_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/maxim         x8+x5+x4+1
 * note:    d for直接计算
 *****************************************************************************/

uint8_t crc8_maxim_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint8_t crc = 0;         // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; i++)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x8c;        // 0x8c = reverse 0x31
            else
                crc >>= 1;
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/cdma2000          x8+x7+x4+x3+x+1
 * poly:    0x9b
 * init:    0xff
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc8cdma2000_table[256] = {
    0x00, 0x9b, 0xad, 0x36, 0xc1, 0x5a, 0x6c, 0xf7, 0x19, 0x82, 0xb4, 0x2f, 0xd8, 0x43, 0x75, 0xee,
    0x32, 0xa9, 0x9f, 0x04, 0xf3, 0x68, 0x5e, 0xc5, 0x2b, 0xb0, 0x86, 0x1d, 0xea, 0x71, 0x47, 0xdc,
    0x64, 0xff, 0xc9, 0x52, 0xa5, 0x3e, 0x08, 0x93, 0x7d, 0xe6, 0xd0, 0x4b, 0xbc, 0x27, 0x11, 0x8a,
    0x56, 0xcd, 0xfb, 0x60, 0x97, 0x0c, 0x3a, 0xa1, 0x4f, 0xd4, 0xe2, 0x79, 0x8e, 0x15, 0x23, 0xb8,
    0xc8, 0x53, 0x65, 0xfe, 0x09, 0x92, 0xa4, 0x3f, 0xd1, 0x4a, 0x7c, 0xe7, 0x10, 0x8b, 0xbd, 0x26,
    0xfa, 0x61, 0x57, 0xcc, 0x3b, 0xa0, 0x96, 0x0d, 0xe3, 0x78, 0x4e, 0xd5, 0x22, 0xb9, 0x8f, 0x14,
    0xac, 0x37, 0x01, 0x9a, 0x6d, 0xf6, 0xc0, 0x5b, 0xb5, 0x2e, 0x18, 0x83, 0x74, 0xef, 0xd9, 0x42,
    0x9e, 0x05, 0x33, 0xa8, 0x5f, 0xc4, 0xf2, 0x69, 0x87, 0x1c, 0x2a, 0xb1, 0x46, 0xdd, 0xeb, 0x70,
    0x0b, 0x90, 0xa6, 0x3d, 0xca, 0x51, 0x67, 0xfc, 0x12, 0x89, 0xbf, 0x24, 0xd3, 0x48, 0x7e, 0xe5,
    0x39, 0xa2, 0x94, 0x0f, 0xf8, 0x63, 0x55, 0xce, 0x20, 0xbb, 0x8d, 0x16, 0xe1, 0x7a, 0x4c, 0xd7,
    0x6f, 0xf4, 0xc2, 0x59, 0xae, 0x35, 0x03, 0x98, 0x76, 0xed, 0xdb, 0x40, 0xb7, 0x2c, 0x1a, 0x81,
    0x5d, 0xc6, 0xf0, 0x6b, 0x9c, 0x07, 0x31, 0xaa, 0x44, 0xdf, 0xe9, 0x72, 0x85, 0x1e, 0x28, 0xb3,
    0xc3, 0x58, 0x6e, 0xf5, 0x02, 0x99, 0xaf, 0x34, 0xda, 0x41, 0x77, 0xec, 0x1b, 0x80, 0xb6, 0x2d,
    0xf1, 0x6a, 0x5c, 0xc7, 0x30, 0xab, 0x9d, 0x06, 0xe8, 0x73, 0x45, 0xde, 0x29, 0xb2, 0x84, 0x1f,
    0xa7, 0x3c, 0x0a, 0x91, 0x66, 0xfd, 0xcb, 0x50, 0xbe, 0x25, 0x13, 0x88, 0x7f, 0xe4, 0xd2, 0x49,
    0x95, 0x0e, 0x38, 0xa3, 0x54, 0xcf, 0xf9, 0x62, 0x8c, 0x17, 0x21, 0xba, 0x4d, 0xd6, 0xe0, 0x7b,
};

/* crc8_cdma2000_calc */
uint8_t crc8_cdma2000_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0xff;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc8cdma2000_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/darc         x8+x5+x4+x3+1
 * poly:    0x39
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * alias:
 *****************************************************************************/
const static uint8_t crc8darc_table[256] = {
    0x00, 0x72, 0xe4, 0x96, 0xf1, 0x83, 0x15, 0x67, 0xdb, 0xa9, 0x3f, 0x4d, 0x2a, 0x58, 0xce, 0xbc,
    0x8f, 0xfd, 0x6b, 0x19, 0x7e, 0x0c, 0x9a, 0xe8, 0x54, 0x26, 0xb0, 0xc2, 0xa5, 0xd7, 0x41, 0x33,
    0x27, 0x55, 0xc3, 0xb1, 0xd6, 0xa4, 0x32, 0x40, 0xfc, 0x8e, 0x18, 0x6a, 0x0d, 0x7f, 0xe9, 0x9b,
    0xa8, 0xda, 0x4c, 0x3e, 0x59, 0x2b, 0xbd, 0xcf, 0x73, 0x01, 0x97, 0xe5, 0x82, 0xf0, 0x66, 0x14,
    0x4e, 0x3c, 0xaa, 0xd8, 0xbf, 0xcd, 0x5b, 0x29, 0x95, 0xe7, 0x71, 0x03, 0x64, 0x16, 0x80, 0xf2,
    0xc1, 0xb3, 0x25, 0x57, 0x30, 0x42, 0xd4, 0xa6, 0x1a, 0x68, 0xfe, 0x8c, 0xeb, 0x99, 0x0f, 0x7d,
    0x69, 0x1b, 0x8d, 0xff, 0x98, 0xea, 0x7c, 0x0e, 0xb2, 0xc0, 0x56, 0x24, 0x43, 0x31, 0xa7, 0xd5,
    0xe6, 0x94, 0x02, 0x70, 0x17, 0x65, 0xf3, 0x81, 0x3d, 0x4f, 0xd9, 0xab, 0xcc, 0xbe, 0x28, 0x5a,
    0x9c, 0xee, 0x78, 0x0a, 0x6d, 0x1f, 0x89, 0xfb, 0x47, 0x35, 0xa3, 0xd1, 0xb6, 0xc4, 0x52, 0x20,
    0x13, 0x61, 0xf7, 0x85, 0xe2, 0x90, 0x06, 0x74, 0xc8, 0xba, 0x2c, 0x5e, 0x39, 0x4b, 0xdd, 0xaf,
    0xbb, 0xc9, 0x5f, 0x2d, 0x4a, 0x38, 0xae, 0xdc, 0x60, 0x12, 0x84, 0xf6, 0x91, 0xe3, 0x75, 0x07,
    0x34, 0x46, 0xd0, 0xa2, 0xc5, 0xb7, 0x21, 0x53, 0xef, 0x9d, 0x0b, 0x79, 0x1e, 0x6c, 0xfa, 0x88,
    0xd2, 0xa0, 0x36, 0x44, 0x23, 0x51, 0xc7, 0xb5, 0x09, 0x7b, 0xed, 0x9f, 0xf8, 0x8a, 0x1c, 0x6e,
    0x5d, 0x2f, 0xb9, 0xcb, 0xac, 0xde, 0x48, 0x3a, 0x86, 0xf4, 0x62, 0x10, 0x77, 0x05, 0x93, 0xe1,
    0xf5, 0x87, 0x11, 0x63, 0x04, 0x76, 0xe0, 0x92, 0x2e, 0x5c, 0xca, 0xb8, 0xdf, 0xad, 0x3b, 0x49,
    0x7a, 0x08, 0x9e, 0xec, 0x8b, 0xf9, 0x6f, 0x1d, 0xa1, 0xd3, 0x45, 0x37, 0x50, 0x22, 0xb4, 0xc6,
};

uint8_t crc8_darc_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc8darc_table[tmp];
    }
    return crc;
}

/******************************************************************************
 * name:    crc-8/dvb-s2          x8+x7+x6+x4+x2+x+1
 * poly:    0xd5
 * init:    0x00
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc8dvb_s2_table[256] = {
    0x00, 0xd5, 0x7f, 0xaa, 0xfe, 0x2b, 0x81, 0x54, 0x29, 0xfc, 0x56, 0x83, 0xd7, 0x02, 0xa8, 0x7d,
    0x52, 0x87, 0x2d, 0xf8, 0xac, 0x79, 0xd3, 0x06, 0x7b, 0xae, 0x04, 0xd1, 0x85, 0x50, 0xfa, 0x2f,
    0xa4, 0x71, 0xdb, 0x0e, 0x5a, 0x8f, 0x25, 0xf0, 0x8d, 0x58, 0xf2, 0x27, 0x73, 0xa6, 0x0c, 0xd9,
    0xf6, 0x23, 0x89, 0x5c, 0x08, 0xdd, 0x77, 0xa2, 0xdf, 0x0a, 0xa0, 0x75, 0x21, 0xf4, 0x5e, 0x8b,
    0x9d, 0x48, 0xe2, 0x37, 0x63, 0xb6, 0x1c, 0xc9, 0xb4, 0x61, 0xcb, 0x1e, 0x4a, 0x9f, 0x35, 0xe0,
    0xcf, 0x1a, 0xb0, 0x65, 0x31, 0xe4, 0x4e, 0x9b, 0xe6, 0x33, 0x99, 0x4c, 0x18, 0xcd, 0x67, 0xb2,
    0x39, 0xec, 0x46, 0x93, 0xc7, 0x12, 0xb8, 0x6d, 0x10, 0xc5, 0x6f, 0xba, 0xee, 0x3b, 0x91, 0x44,
    0x6b, 0xbe, 0x14, 0xc1, 0x95, 0x40, 0xea, 0x3f, 0x42, 0x97, 0x3d, 0xe8, 0xbc, 0x69, 0xc3, 0x16,
    0xef, 0x3a, 0x90, 0x45, 0x11, 0xc4, 0x6e, 0xbb, 0xc6, 0x13, 0xb9, 0x6c, 0x38, 0xed, 0x47, 0x92,
    0xbd, 0x68, 0xc2, 0x17, 0x43, 0x96, 0x3c, 0xe9, 0x94, 0x41, 0xeb, 0x3e, 0x6a, 0xbf, 0x15, 0xc0,
    0x4b, 0x9e, 0x34, 0xe1, 0xb5, 0x60, 0xca, 0x1f, 0x62, 0xb7, 0x1d, 0xc8, 0x9c, 0x49, 0xe3, 0x36,
    0x19, 0xcc, 0x66, 0xb3, 0xe7, 0x32, 0x98, 0x4d, 0x30, 0xe5, 0x4f, 0x9a, 0xce, 0x1b, 0xb1, 0x64,
    0x72, 0xa7, 0x0d, 0xd8, 0x8c, 0x59, 0xf3, 0x26, 0x5b, 0x8e, 0x24, 0xf1, 0xa5, 0x70, 0xda, 0x0f,
    0x20, 0xf5, 0x5f, 0x8a, 0xde, 0x0b, 0xa1, 0x74, 0x09, 0xdc, 0x76, 0xa3, 0xf7, 0x22, 0x88, 0x5d,
    0xd6, 0x03, 0xa9, 0x7c, 0x28, 0xfd, 0x57, 0x82, 0xff, 0x2a, 0x80, 0x55, 0x01, 0xd4, 0x7e, 0xab,
    0x84, 0x51, 0xfb, 0x2e, 0x7a, 0xaf, 0x05, 0xd0, 0xad, 0x78, 0xd2, 0x07, 0x53, 0x86, 0x2c, 0xf9,
};

/* crc8_dvb_s2_calc */
uint8_t crc8_dvb_s2_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc8dvb_s2_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/ebu         x8+x4++x3+x2+1
 * poly:    0x1d
 * init:    0xff
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * alias:
 *****************************************************************************/
const static uint8_t crc8ebu_table[256] = {
    0x00, 0x64, 0xc8, 0xac, 0xe1, 0x85, 0x29, 0x4d, 0xb3, 0xd7, 0x7b, 0x1f, 0x52, 0x36, 0x9a, 0xfe,
    0x17, 0x73, 0xdf, 0xbb, 0xf6, 0x92, 0x3e, 0x5a, 0xa4, 0xc0, 0x6c, 0x08, 0x45, 0x21, 0x8d, 0xe9,
    0x2e, 0x4a, 0xe6, 0x82, 0xcf, 0xab, 0x07, 0x63, 0x9d, 0xf9, 0x55, 0x31, 0x7c, 0x18, 0xb4, 0xd0,
    0x39, 0x5d, 0xf1, 0x95, 0xd8, 0xbc, 0x10, 0x74, 0x8a, 0xee, 0x42, 0x26, 0x6b, 0x0f, 0xa3, 0xc7,
    0x5c, 0x38, 0x94, 0xf0, 0xbd, 0xd9, 0x75, 0x11, 0xef, 0x8b, 0x27, 0x43, 0x0e, 0x6a, 0xc6, 0xa2,
    0x4b, 0x2f, 0x83, 0xe7, 0xaa, 0xce, 0x62, 0x06, 0xf8, 0x9c, 0x30, 0x54, 0x19, 0x7d, 0xd1, 0xb5,
    0x72, 0x16, 0xba, 0xde, 0x93, 0xf7, 0x5b, 0x3f, 0xc1, 0xa5, 0x09, 0x6d, 0x20, 0x44, 0xe8, 0x8c,
    0x65, 0x01, 0xad, 0xc9, 0x84, 0xe0, 0x4c, 0x28, 0xd6, 0xb2, 0x1e, 0x7a, 0x37, 0x53, 0xff, 0x9b,
    0xb8, 0xdc, 0x70, 0x14, 0x59, 0x3d, 0x91, 0xf5, 0x0b, 0x6f, 0xc3, 0xa7, 0xea, 0x8e, 0x22, 0x46,
    0xaf, 0xcb, 0x67, 0x03, 0x4e, 0x2a, 0x86, 0xe2, 0x1c, 0x78, 0xd4, 0xb0, 0xfd, 0x99, 0x35, 0x51,
    0x96, 0xf2, 0x5e, 0x3a, 0x77, 0x13, 0xbf, 0xdb, 0x25, 0x41, 0xed, 0x89, 0xc4, 0xa0, 0x0c, 0x68,
    0x81, 0xe5, 0x49, 0x2d, 0x60, 0x04, 0xa8, 0xcc, 0x32, 0x56, 0xfa, 0x9e, 0xd3, 0xb7, 0x1b, 0x7f,
    0xe4, 0x80, 0x2c, 0x48, 0x05, 0x61, 0xcd, 0xa9, 0x57, 0x33, 0x9f, 0xfb, 0xb6, 0xd2, 0x7e, 0x1a,
    0xf3, 0x97, 0x3b, 0x5f, 0x12, 0x76, 0xda, 0xbe, 0x40, 0x24, 0x88, 0xec, 0xa1, 0xc5, 0x69, 0x0d,
    0xca, 0xae, 0x02, 0x66, 0x2b, 0x4f, 0xe3, 0x87, 0x79, 0x1d, 0xb1, 0xd5, 0x98, 0xfc, 0x50, 0x34,
    0xdd, 0xb9, 0x15, 0x71, 0x3c, 0x58, 0xf4, 0x90, 0x6e, 0x0a, 0xa6, 0xc2, 0x8f, 0xeb, 0x47, 0x23,
};

uint8_t crc8_ebu_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0xff;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc8ebu_table[tmp];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-8/i-code          x8+x7+x6+x4+x2+x+1
 * poly:    0x1d
 * init:    0xfd
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint8_t crc8i_code_table[256] = {
    0x00, 0xd5, 0x7f, 0xaa, 0xfe, 0x2b, 0x81, 0x54, 0x29, 0xfc, 0x56, 0x83, 0xd7, 0x02, 0xa8, 0x7d,
    0x52, 0x87, 0x2d, 0xf8, 0xac, 0x79, 0xd3, 0x06, 0x7b, 0xae, 0x04, 0xd1, 0x85, 0x50, 0xfa, 0x2f,
    0xa4, 0x71, 0xdb, 0x0e, 0x5a, 0x8f, 0x25, 0xf0, 0x8d, 0x58, 0xf2, 0x27, 0x73, 0xa6, 0x0c, 0xd9,
    0xf6, 0x23, 0x89, 0x5c, 0x08, 0xdd, 0x77, 0xa2, 0xdf, 0x0a, 0xa0, 0x75, 0x21, 0xf4, 0x5e, 0x8b,
    0x9d, 0x48, 0xe2, 0x37, 0x63, 0xb6, 0x1c, 0xc9, 0xb4, 0x61, 0xcb, 0x1e, 0x4a, 0x9f, 0x35, 0xe0,
    0xcf, 0x1a, 0xb0, 0x65, 0x31, 0xe4, 0x4e, 0x9b, 0xe6, 0x33, 0x99, 0x4c, 0x18, 0xcd, 0x67, 0xb2,
    0x39, 0xec, 0x46, 0x93, 0xc7, 0x12, 0xb8, 0x6d, 0x10, 0xc5, 0x6f, 0xba, 0xee, 0x3b, 0x91, 0x44,
    0x6b, 0xbe, 0x14, 0xc1, 0x95, 0x40, 0xea, 0x3f, 0x42, 0x97, 0x3d, 0xe8, 0xbc, 0x69, 0xc3, 0x16,
    0xef, 0x3a, 0x90, 0x45, 0x11, 0xc4, 0x6e, 0xbb, 0xc6, 0x13, 0xb9, 0x6c, 0x38, 0xed, 0x47, 0x92,
    0xbd, 0x68, 0xc2, 0x17, 0x43, 0x96, 0x3c, 0xe9, 0x94, 0x41, 0xeb, 0x3e, 0x6a, 0xbf, 0x15, 0xc0,
    0x4b, 0x9e, 0x34, 0xe1, 0xb5, 0x60, 0xca, 0x1f, 0x62, 0xb7, 0x1d, 0xc8, 0x9c, 0x49, 0xe3, 0x36,
    0x19, 0xcc, 0x66, 0xb3, 0xe7, 0x32, 0x98, 0x4d, 0x30, 0xe5, 0x4f, 0x9a, 0xce, 0x1b, 0xb1, 0x64,
    0x72, 0xa7, 0x0d, 0xd8, 0x8c, 0x59, 0xf3, 0x26, 0x5b, 0x8e, 0x24, 0xf1, 0xa5, 0x70, 0xda, 0x0f,
    0x20, 0xf5, 0x5f, 0x8a, 0xde, 0x0b, 0xa1, 0x74, 0x09, 0xdc, 0x76, 0xa3, 0xf7, 0x22, 0x88, 0x5d,
    0xd6, 0x03, 0xa9, 0x7c, 0x28, 0xfd, 0x57, 0x82, 0xff, 0x2a, 0x80, 0x55, 0x01, 0xd4, 0x7e, 0xab,
    0x84, 0x51, 0xfb, 0x2e, 0x7a, 0xaf, 0x05, 0xd0, 0xad, 0x78, 0xd2, 0x07, 0x53, 0x86, 0x2c, 0xf9,
};

/* crc8_i_code_calc */
uint8_t crc8_i_code_calc(uint8_t *data, uint32_t length)
{
    uint8_t crc = 0xfd;
    uint8_t tmp = 0;
    while (length--)
    {
        tmp = crc ^ *data++;
        crc = crc8i_code_table[tmp];
    }
    return crc;
}

/******************************************************************************
 * name:    crc-8/wcdma          x8+x7+x4+x3+x+1
 * poly:    0x9b
 * init:    0x00
 * refin:   true
 * refout:  true
 * xorout:  0x00
 * alias:
 *****************************************************************************/
const static uint8_t crc8wcdma_table[256] = {
    0x00, 0x64, 0xc8, 0xac, 0xe1, 0x85, 0x29, 0x4d, 0xb3, 0xd7, 0x7b, 0x1f, 0x52, 0x36, 0x9a, 0xfe,
    0x17, 0x73, 0xdf, 0xbb, 0xf6, 0x92, 0x3e, 0x5a, 0xa4, 0xc0, 0x6c, 0x08, 0x45, 0x21, 0x8d, 0xe9,
    0x2e, 0x4a, 0xe6, 0x82, 0xcf, 0xab, 0x07, 0x63, 0x9d, 0xf9, 0x55, 0x31, 0x7c, 0x18, 0xb4, 0xd0,
    0x39, 0x5d, 0xf1, 0x95, 0xd8, 0xbc, 0x10, 0x74, 0x8a, 0xee, 0x42, 0x26, 0x6b, 0x0f, 0xa3, 0xc7,
    0x5c, 0x38, 0x94, 0xf0, 0xbd, 0xd9, 0x75, 0x11, 0xef, 0x8b, 0x27, 0x43, 0x0e, 0x6a, 0xc6, 0xa2,
    0x4b, 0x2f, 0x83, 0xe7, 0xaa, 0xce, 0x62, 0x06, 0xf8, 0x9c, 0x30, 0x54, 0x19, 0x7d, 0xd1, 0xb5,
    0x72, 0x16, 0xba, 0xde, 0x93, 0xf7, 0x5b, 0x3f, 0xc1, 0xa5, 0x09, 0x6d, 0x20, 0x44, 0xe8, 0x8c,
    0x65, 0x01, 0xad, 0xc9, 0x84, 0xe0, 0x4c, 0x28, 0xd6, 0xb2, 0x1e, 0x7a, 0x37, 0x53, 0xff, 0x9b,
    0xb8, 0xdc, 0x70, 0x14, 0x59, 0x3d, 0x91, 0xf5, 0x0b, 0x6f, 0xc3, 0xa7, 0xea, 0x8e, 0x22, 0x46,
    0xaf, 0xcb, 0x67, 0x03, 0x4e, 0x2a, 0x86, 0xe2, 0x1c, 0x78, 0xd4, 0xb0, 0xfd, 0x99, 0x35, 0x51,
    0x96, 0xf2, 0x5e, 0x3a, 0x77, 0x13, 0xbf, 0xdb, 0x25, 0x41, 0xed, 0x89, 0xc4, 0xa0, 0x0c, 0x68,
    0x81, 0xe5, 0x49, 0x2d, 0x60, 0x04, 0xa8, 0xcc, 0x32, 0x56, 0xfa, 0x9e, 0xd3, 0xb7, 0x1b, 0x7f,
    0xe4, 0x80, 0x2c, 0x48, 0x05, 0x61, 0xcd, 0xa9, 0x57, 0x33, 0x9f, 0xfb, 0xb6, 0xd2, 0x7e, 0x1a,
    0xf3, 0x97, 0x3b, 0x5f, 0x12, 0x76, 0xda, 0xbe, 0x40, 0x24, 0x88, 0xec, 0xa1, 0xc5, 0x69, 0x0d,
    0xca, 0xae, 0x02, 0x66, 0x2b, 0x4f, 0xe3, 0x87, 0x79, 0x1d, 0xb1, 0xd5, 0x98, 0xfc, 0x50, 0x34,
    0xdd, 0xb9, 0x15, 0x71, 0x3c, 0x58, 0xf4, 0x90, 0x6e, 0x0a, 0xa6, 0xc2, 0x8f, 0xeb, 0x47, 0x23,
};

uint8_t crc8_wcdma_calc(uint8_t *data, uint32_t length)
{
    uint8_t tmp = 0;
    uint8_t crc = 0;                // initial value
    while (length--)
    {
        tmp = crc ^ *data++;                 // crc ^= *data; data++;
        crc = crc8wcdma_table[tmp];
    }
    return crc;
}


/******************************************************************************
 * name:    crc-16/ibm          x16+x15+x2+1
 * poly:    0x8005
 * init:    0x0000
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * alias:   crc-16,crc-16/arc,crc-16/lha
 *****************************************************************************/
const static uint16_t crc16ibm_table[256] = {
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
};

uint16_t crc16_ibm_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ibm_table[tmp & 0xff];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-16/ibm          x16+x15+x2+1
 * note:    d for直接计算
 *****************************************************************************/

uint16_t crc16_ibm_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xa001;        // 0xa001 = reverse 0x8005
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}

/******************************************************************************
 * name:    crc-16/maxim        x16+x15+x2+1
 * poly:    0x8005
 * init:    0x0000
 * refin:   true
 * refout:  true
 * xorout:  0xffff
 * note:
 *****************************************************************************/


uint16_t crc16_maxim_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ibm_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}

/******************************************************************************
 * name:    crc-16/maxim          x16+x15+x2+1
 * note:    d for直接计算
 *****************************************************************************/

uint16_t crc16_maxim_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xa001;        // 0xa001 = reverse 0x8005
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;    // crc^0xffff
}
/******************************************************************************
 * name:    crc-16/usb          x16+x15+x2+1
 * poly:    0x8005
 * init:    0xffff
 * refin:   true
 * refout:  true
 * xorout:  0xffff
 * note:
 *****************************************************************************/

uint16_t crc16_usb_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ibm_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}

/******************************************************************************
 * name:    crc-16/usb          x16+x15+x2+1
 * note:    d for直接计算
 *****************************************************************************/

uint16_t crc16_usb_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0xffff;        // initial value
    while (length--)
    {
        crc ^= *data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xa001;        // 0xa001 = reverse 0x8005
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;    // crc^0xffff
}
/******************************************************************************
 * name:    crc-16/modbus       x16+x15+x2+1
 * poly:    0x8005
 * init:    0xffff
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * note:
 *****************************************************************************/
uint16_t crc16_modbus_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ibm_table[tmp & 0xff];
    }
    return crc; // crc
}


/******************************************************************************
 * name:    crc-16/modbus       x16+x15+x2+1
 * note:    d for直接计算
 *****************************************************************************/

uint16_t crc16_modbus_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0xffff;        // initial value
    while (length--)
    {
        crc ^= *data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xa001;        // 0xa001 = reverse 0x8005
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}

/******************************************************************************
 * name:    crc-16/ccitt        x16+x12+x5+1
 * poly:    0x1021
 * init:    0x0000
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * alias:   crc-ccitt,crc-16/ccitt-true,crc-16/kermit
 *****************************************************************************/
const static uint16_t crc16ccitt_table[256] = {
    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
};

uint16_t crc16_ccitt_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-16/ccitt        x16+x12+x5+1
 * note:    d for直接计算
 *****************************************************************************/
uint16_t crc16_ccitt_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0;        // initial value
    while (length--)
    {
        crc ^= *data++;        // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x8408;        // 0x8408 = reverse 0x1021
            else
                crc = (crc >> 1);
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-16/ccitt-false   x16+x12+x5+1
 * poly:    0x1021
 * init:    0xffff
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * note:
 *****************************************************************************/
const static uint16_t crc16ccitt_false_table[256] = {
    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
};

uint16_t crc16_ccitt_false_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16ccitt_false_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-16/ccitt-false   x16+x12+x5+1
 * note:    d for直接计算
 *****************************************************************************/
uint16_t crc16_ccitt_false_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0xffff;        //initial value
    while (length--)
    {
        crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint6_t)(*data)<<8; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 0x8000)
                crc = (crc << 1) ^ 0x1021;
            else
                crc <<= 1;
        }
    }
    return crc;
}
/******************************************************************************
 * name:    crc-16/x25          x16+x12+x5+1
 * poly:    0x1021
 * init:    0xffff
 * refin:   true
 * refout:  true
 * xorout:  0xffff
 * note:
 *****************************************************************************/

uint16_t crc16_x25_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}

/******************************************************************************
 * name:    crc-16/x25          x16+x12+x5+1
 * note:    d for直接计算
 *****************************************************************************/

uint16_t crc16_x25_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0xffff;        // initial value
    while (length--)
    {
        crc ^= *data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x8408;        // 0x8408 = reverse 0x1021
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;                // crc^xorout
}

/******************************************************************************
 * name:    crc-16/xmodem       x16+x12+x5+1
 * poly:    0x1021
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * alias:   crc-16/zmodem,crc-16/acorn
 *****************************************************************************/

uint16_t crc16_xmodem_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16ccitt_false_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-16/xmodem       x16+x12+x5+1
 * note:    d for直接计算
 *****************************************************************************/
uint16_t crc16_xmodem_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0;            // initial value
    while (length--)
    {
        crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 0x8000)
                crc = (crc << 1) ^ 0x1021;
            else
                crc <<= 1;
        }
    }
    return crc;
}


/******************************************************************************
 * name:    crc-16/dnp          x16+x13+x12+x11+x10+x8+x6+x5+x2+1
 * poly:    0x3d65
 * init:    0x0000
 * refin:   true
 * refout:  true
 * xorout:  0xffff
 * use:     m-bus,ect.
 *****************************************************************************/

const static uint16_t crc16dnp_table[256] = {
    0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a, 0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
    0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1, 0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
    0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35, 0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
    0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e, 0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
    0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4, 0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
    0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af, 0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
    0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b, 0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
    0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00, 0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
    0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526, 0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
    0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d, 0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
    0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89, 0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
    0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2, 0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
    0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678, 0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
    0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413, 0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
    0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7, 0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
    0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc, 0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235,
};

uint16_t crc16_dnp_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16dnp_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}

/******************************************************************************
 * name:    crc-16/dnp          x16+x13+x12+x11+x10+x8+x6+x5+x2+1
 * note:    d for直接计算
 *****************************************************************************/
uint16_t crc16_dnp_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint16_t crc = 0;            // initial value
    while (length--)
    {
        crc ^= *data++;            // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xa6bc;        // 0xa6bc = reverse 0x3d65
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;   // crc^xorout
}



/******************************************************************************
 * name:    crc-16/aug-ccitt       x16+x12+x5+1
 * poly:    0x1021
 * init:    0x1d0f
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * alias:
 *****************************************************************************/
uint16_t crc16_aug_ccitt_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0x1d0f;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16ccitt_false_table[tmp & 0xff];
    }
    return crc; // crc
}


/******************************************************************************
 * name:    crc-16/buypass          x16+x15+x2+1
 * poly:    0x8005
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * alias:
 *****************************************************************************/
const static uint16_t crc16butpass_table[256] = {
    0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
    0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
    0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
    0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
    0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
    0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
    0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
    0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
    0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
    0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
    0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
    0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
    0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
    0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
    0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
    0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202,
};

uint16_t crc16_buypass_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16butpass_table[tmp & 0xff];
    }
    return crc;
}

/******************************************************************************
 * name:    crc-16/cdma2000          x16+x15+x14+x11+x6+x5+x2+x+1
 * poly:    0xc867
 * init:    0xffff
 * refin:   false
 * refout:  false
 * xorout:  0x00
 * note:
 *****************************************************************************/
const static uint16_t crc16cdma2000_table[256] = {
    0x0000, 0xc867, 0x58a9, 0x90ce, 0xb152, 0x7935, 0xe9fb, 0x219c, 0xaac3, 0x62a4, 0xf26a, 0x3a0d, 0x1b91, 0xd3f6, 0x4338, 0x8b5f,
    0x9de1, 0x5586, 0xc548, 0x0d2f, 0x2cb3, 0xe4d4, 0x741a, 0xbc7d, 0x3722, 0xff45, 0x6f8b, 0xa7ec, 0x8670, 0x4e17, 0xded9, 0x16be,
    0xf3a5, 0x3bc2, 0xab0c, 0x636b, 0x42f7, 0x8a90, 0x1a5e, 0xd239, 0x5966, 0x9101, 0x01cf, 0xc9a8, 0xe834, 0x2053, 0xb09d, 0x78fa,
    0x6e44, 0xa623, 0x36ed, 0xfe8a, 0xdf16, 0x1771, 0x87bf, 0x4fd8, 0xc487, 0x0ce0, 0x9c2e, 0x5449, 0x75d5, 0xbdb2, 0x2d7c, 0xe51b,
    0x2f2d, 0xe74a, 0x7784, 0xbfe3, 0x9e7f, 0x5618, 0xc6d6, 0x0eb1, 0x85ee, 0x4d89, 0xdd47, 0x1520, 0x34bc, 0xfcdb, 0x6c15, 0xa472,
    0xb2cc, 0x7aab, 0xea65, 0x2202, 0x039e, 0xcbf9, 0x5b37, 0x9350, 0x180f, 0xd068, 0x40a6, 0x88c1, 0xa95d, 0x613a, 0xf1f4, 0x3993,
    0xdc88, 0x14ef, 0x8421, 0x4c46, 0x6dda, 0xa5bd, 0x3573, 0xfd14, 0x764b, 0xbe2c, 0x2ee2, 0xe685, 0xc719, 0x0f7e, 0x9fb0, 0x57d7,
    0x4169, 0x890e, 0x19c0, 0xd1a7, 0xf03b, 0x385c, 0xa892, 0x60f5, 0xebaa, 0x23cd, 0xb303, 0x7b64, 0x5af8, 0x929f, 0x0251, 0xca36,
    0x5e5a, 0x963d, 0x06f3, 0xce94, 0xef08, 0x276f, 0xb7a1, 0x7fc6, 0xf499, 0x3cfe, 0xac30, 0x6457, 0x45cb, 0x8dac, 0x1d62, 0xd505,
    0xc3bb, 0x0bdc, 0x9b12, 0x5375, 0x72e9, 0xba8e, 0x2a40, 0xe227, 0x6978, 0xa11f, 0x31d1, 0xf9b6, 0xd82a, 0x104d, 0x8083, 0x48e4,
    0xadff, 0x6598, 0xf556, 0x3d31, 0x1cad, 0xd4ca, 0x4404, 0x8c63, 0x073c, 0xcf5b, 0x5f95, 0x97f2, 0xb66e, 0x7e09, 0xeec7, 0x26a0,
    0x301e, 0xf879, 0x68b7, 0xa0d0, 0x814c, 0x492b, 0xd9e5, 0x1182, 0x9add, 0x52ba, 0xc274, 0x0a13, 0x2b8f, 0xe3e8, 0x7326, 0xbb41,
    0x7177, 0xb910, 0x29de, 0xe1b9, 0xc025, 0x0842, 0x988c, 0x50eb, 0xdbb4, 0x13d3, 0x831d, 0x4b7a, 0x6ae6, 0xa281, 0x324f, 0xfa28,
    0xec96, 0x24f1, 0xb43f, 0x7c58, 0x5dc4, 0x95a3, 0x056d, 0xcd0a, 0x4655, 0x8e32, 0x1efc, 0xd69b, 0xf707, 0x3f60, 0xafae, 0x67c9,
    0x82d2, 0x4ab5, 0xda7b, 0x121c, 0x3380, 0xfbe7, 0x6b29, 0xa34e, 0x2811, 0xe076, 0x70b8, 0xb8df, 0x9943, 0x5124, 0xc1ea, 0x098d,
    0x1f33, 0xd754, 0x479a, 0x8ffd, 0xae61, 0x6606, 0xf6c8, 0x3eaf, 0xb5f0, 0x7d97, 0xed59, 0x253e, 0x04a2, 0xccc5, 0x5c0b, 0x946c,
};

uint16_t crc16_cdma2000_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16cdma2000_table[tmp & 0xff];
    }
    return crc; // crc
}



/******************************************************************************
 * name:    crc-16/dds-110          x16+x15+x2+1
 * poly:    0x8005
 * init:    0x800d
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * alias:
 *****************************************************************************/

uint16_t crc16_dds_110_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0x800d;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16butpass_table[tmp & 0xff];
    }
    return crc;
}
/******************************************************************************
 * name:    crc-16/dect-r          x10+x8+x7+x3+x+1
 * poly:    0x0589
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0001
 * alias:
 *****************************************************************************/
const static uint16_t crc16dect_r_table[256] = {
    0x0000, 0x0589, 0x0b12, 0x0e9b, 0x1624, 0x13ad, 0x1d36, 0x18bf, 0x2c48, 0x29c1, 0x275a, 0x22d3, 0x3a6c, 0x3fe5, 0x317e, 0x34f7,
    0x5890, 0x5d19, 0x5382, 0x560b, 0x4eb4, 0x4b3d, 0x45a6, 0x402f, 0x74d8, 0x7151, 0x7fca, 0x7a43, 0x62fc, 0x6775, 0x69ee, 0x6c67,
    0xb120, 0xb4a9, 0xba32, 0xbfbb, 0xa704, 0xa28d, 0xac16, 0xa99f, 0x9d68, 0x98e1, 0x967a, 0x93f3, 0x8b4c, 0x8ec5, 0x805e, 0x85d7,
    0xe9b0, 0xec39, 0xe2a2, 0xe72b, 0xff94, 0xfa1d, 0xf486, 0xf10f, 0xc5f8, 0xc071, 0xceea, 0xcb63, 0xd3dc, 0xd655, 0xd8ce, 0xdd47,
    0x67c9, 0x6240, 0x6cdb, 0x6952, 0x71ed, 0x7464, 0x7aff, 0x7f76, 0x4b81, 0x4e08, 0x4093, 0x451a, 0x5da5, 0x582c, 0x56b7, 0x533e,
    0x3f59, 0x3ad0, 0x344b, 0x31c2, 0x297d, 0x2cf4, 0x226f, 0x27e6, 0x1311, 0x1698, 0x1803, 0x1d8a, 0x0535, 0x00bc, 0x0e27, 0x0bae,
    0xd6e9, 0xd360, 0xddfb, 0xd872, 0xc0cd, 0xc544, 0xcbdf, 0xce56, 0xfaa1, 0xff28, 0xf1b3, 0xf43a, 0xec85, 0xe90c, 0xe797, 0xe21e,
    0x8e79, 0x8bf0, 0x856b, 0x80e2, 0x985d, 0x9dd4, 0x934f, 0x96c6, 0xa231, 0xa7b8, 0xa923, 0xacaa, 0xb415, 0xb19c, 0xbf07, 0xba8e,
    0xcf92, 0xca1b, 0xc480, 0xc109, 0xd9b6, 0xdc3f, 0xd2a4, 0xd72d, 0xe3da, 0xe653, 0xe8c8, 0xed41, 0xf5fe, 0xf077, 0xfeec, 0xfb65,
    0x9702, 0x928b, 0x9c10, 0x9999, 0x8126, 0x84af, 0x8a34, 0x8fbd, 0xbb4a, 0xbec3, 0xb058, 0xb5d1, 0xad6e, 0xa8e7, 0xa67c, 0xa3f5,
    0x7eb2, 0x7b3b, 0x75a0, 0x7029, 0x6896, 0x6d1f, 0x6384, 0x660d, 0x52fa, 0x5773, 0x59e8, 0x5c61, 0x44de, 0x4157, 0x4fcc, 0x4a45,
    0x2622, 0x23ab, 0x2d30, 0x28b9, 0x3006, 0x358f, 0x3b14, 0x3e9d, 0x0a6a, 0x0fe3, 0x0178, 0x04f1, 0x1c4e, 0x19c7, 0x175c, 0x12d5,
    0xa85b, 0xadd2, 0xa349, 0xa6c0, 0xbe7f, 0xbbf6, 0xb56d, 0xb0e4, 0x8413, 0x819a, 0x8f01, 0x8a88, 0x9237, 0x97be, 0x9925, 0x9cac,
    0xf0cb, 0xf542, 0xfbd9, 0xfe50, 0xe6ef, 0xe366, 0xedfd, 0xe874, 0xdc83, 0xd90a, 0xd791, 0xd218, 0xcaa7, 0xcf2e, 0xc1b5, 0xc43c,
    0x197b, 0x1cf2, 0x1269, 0x17e0, 0x0f5f, 0x0ad6, 0x044d, 0x01c4, 0x3533, 0x30ba, 0x3e21, 0x3ba8, 0x2317, 0x269e, 0x2805, 0x2d8c,
    0x41eb, 0x4462, 0x4af9, 0x4f70, 0x57cf, 0x5246, 0x5cdd, 0x5954, 0x6da3, 0x682a, 0x66b1, 0x6338, 0x7b87, 0x7e0e, 0x7095, 0x751c,
};

uint16_t crc16_dect_r_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16dect_r_table[tmp & 0xff];
    }
    return crc ^ 0x0001; // crc
}

/******************************************************************************
 * name:    crc-16/dect-x          x10+x8+x7+x3+x+1
 * poly:    0x0589
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * alias:
 *****************************************************************************/
uint16_t crc16_dect_x_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16dect_r_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-16/en-13757          x16+x13+x12+x11+x10+x8+x6+x5+x2+1
 * poly:    0x3d65
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0xffff
 * alias:
 *****************************************************************************/
const static uint16_t crc16en_13757_table[256] = {
    0x0000, 0x3d65, 0x7aca, 0x47af, 0xf594, 0xc8f1, 0x8f5e, 0xb23b, 0xd64d, 0xeb28, 0xac87, 0x91e2, 0x23d9, 0x1ebc, 0x5913, 0x6476,
    0x91ff, 0xac9a, 0xeb35, 0xd650, 0x646b, 0x590e, 0x1ea1, 0x23c4, 0x47b2, 0x7ad7, 0x3d78, 0x001d, 0xb226, 0x8f43, 0xc8ec, 0xf589,
    0x1e9b, 0x23fe, 0x6451, 0x5934, 0xeb0f, 0xd66a, 0x91c5, 0xaca0, 0xc8d6, 0xf5b3, 0xb21c, 0x8f79, 0x3d42, 0x0027, 0x4788, 0x7aed,
    0x8f64, 0xb201, 0xf5ae, 0xc8cb, 0x7af0, 0x4795, 0x003a, 0x3d5f, 0x5929, 0x644c, 0x23e3, 0x1e86, 0xacbd, 0x91d8, 0xd677, 0xeb12,
    0x3d36, 0x0053, 0x47fc, 0x7a99, 0xc8a2, 0xf5c7, 0xb268, 0x8f0d, 0xeb7b, 0xd61e, 0x91b1, 0xacd4, 0x1eef, 0x238a, 0x6425, 0x5940,
    0xacc9, 0x91ac, 0xd603, 0xeb66, 0x595d, 0x6438, 0x2397, 0x1ef2, 0x7a84, 0x47e1, 0x004e, 0x3d2b, 0x8f10, 0xb275, 0xf5da, 0xc8bf,
    0x23ad, 0x1ec8, 0x5967, 0x6402, 0xd639, 0xeb5c, 0xacf3, 0x9196, 0xf5e0, 0xc885, 0x8f2a, 0xb24f, 0x0074, 0x3d11, 0x7abe, 0x47db,
    0xb252, 0x8f37, 0xc898, 0xf5fd, 0x47c6, 0x7aa3, 0x3d0c, 0x0069, 0x641f, 0x597a, 0x1ed5, 0x23b0, 0x918b, 0xacee, 0xeb41, 0xd624,
    0x7a6c, 0x4709, 0x00a6, 0x3dc3, 0x8ff8, 0xb29d, 0xf532, 0xc857, 0xac21, 0x9144, 0xd6eb, 0xeb8e, 0x59b5, 0x64d0, 0x237f, 0x1e1a,
    0xeb93, 0xd6f6, 0x9159, 0xac3c, 0x1e07, 0x2362, 0x64cd, 0x59a8, 0x3dde, 0x00bb, 0x4714, 0x7a71, 0xc84a, 0xf52f, 0xb280, 0x8fe5,
    0x64f7, 0x5992, 0x1e3d, 0x2358, 0x9163, 0xac06, 0xeba9, 0xd6cc, 0xb2ba, 0x8fdf, 0xc870, 0xf515, 0x472e, 0x7a4b, 0x3de4, 0x0081,
    0xf508, 0xc86d, 0x8fc2, 0xb2a7, 0x009c, 0x3df9, 0x7a56, 0x4733, 0x2345, 0x1e20, 0x598f, 0x64ea, 0xd6d1, 0xebb4, 0xac1b, 0x917e,
    0x475a, 0x7a3f, 0x3d90, 0x00f5, 0xb2ce, 0x8fab, 0xc804, 0xf561, 0x9117, 0xac72, 0xebdd, 0xd6b8, 0x6483, 0x59e6, 0x1e49, 0x232c,
    0xd6a5, 0xebc0, 0xac6f, 0x910a, 0x2331, 0x1e54, 0x59fb, 0x649e, 0x00e8, 0x3d8d, 0x7a22, 0x4747, 0xf57c, 0xc819, 0x8fb6, 0xb2d3,
    0x59c1, 0x64a4, 0x230b, 0x1e6e, 0xac55, 0x9130, 0xd69f, 0xebfa, 0x8f8c, 0xb2e9, 0xf546, 0xc823, 0x7a18, 0x477d, 0x00d2, 0x3db7,
    0xc83e, 0xf55b, 0xb2f4, 0x8f91, 0x3daa, 0x00cf, 0x4760, 0x7a05, 0x1e73, 0x2316, 0x64b9, 0x59dc, 0xebe7, 0xd682, 0x912d, 0xac48,
};

uint16_t crc16_en_13757_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16en_13757_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}


/******************************************************************************
 * name:    crc-16/genibus      x16+x12+x5+1
 * poly:    0x1021
 * init:    0xffff
 * refin:   false
 * refout:  false
 * xorout:  0xffff
 * note:
 *****************************************************************************/

uint16_t crc16_genibus_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16ccitt_false_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffff
}

/******************************************************************************
 * name:    crc-16/mcrf4xxx          x16+x12+x5+1
 * poly:    0x1021
 * init:    0xffff
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * note:
 *****************************************************************************/
uint16_t crc16_mcrf4xx_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0xffff;                // initial value
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-16/riello          x16+x12+x5+1
 * poly:    0x1021
 * init:    0xb2aa
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * note:
 *****************************************************************************/
uint16_t crc16_riello_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0x554d;                // initial value    // 0x554d = reverse 0xb2aa
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return crc; // crc
}
/******************************************************************************
 * name:    crc-16/t10-dfif     x16+x15+x14+x12+x11+x9+x8+x7+x5+x4+x2+x+1
 * poly:    0x8bb7
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * note:
 *****************************************************************************/
const static uint16_t crc16t10_dif_table[256] = {
    0x0000, 0x8bb7, 0x9cd9, 0x176e, 0xb205, 0x39b2, 0x2edc, 0xa56b, 0xefbd, 0x640a, 0x7364, 0xf8d3, 0x5db8, 0xd60f, 0xc161, 0x4ad6,
    0x54cd, 0xdf7a, 0xc814, 0x43a3, 0xe6c8, 0x6d7f, 0x7a11, 0xf1a6, 0xbb70, 0x30c7, 0x27a9, 0xac1e, 0x0975, 0x82c2, 0x95ac, 0x1e1b,
    0xa99a, 0x222d, 0x3543, 0xbef4, 0x1b9f, 0x9028, 0x8746, 0x0cf1, 0x4627, 0xcd90, 0xdafe, 0x5149, 0xf422, 0x7f95, 0x68fb, 0xe34c,
    0xfd57, 0x76e0, 0x618e, 0xea39, 0x4f52, 0xc4e5, 0xd38b, 0x583c, 0x12ea, 0x995d, 0x8e33, 0x0584, 0xa0ef, 0x2b58, 0x3c36, 0xb781,
    0xd883, 0x5334, 0x445a, 0xcfed, 0x6a86, 0xe131, 0xf65f, 0x7de8, 0x373e, 0xbc89, 0xabe7, 0x2050, 0x853b, 0x0e8c, 0x19e2, 0x9255,
    0x8c4e, 0x07f9, 0x1097, 0x9b20, 0x3e4b, 0xb5fc, 0xa292, 0x2925, 0x63f3, 0xe844, 0xff2a, 0x749d, 0xd1f6, 0x5a41, 0x4d2f, 0xc698,
    0x7119, 0xfaae, 0xedc0, 0x6677, 0xc31c, 0x48ab, 0x5fc5, 0xd472, 0x9ea4, 0x1513, 0x027d, 0x89ca, 0x2ca1, 0xa716, 0xb078, 0x3bcf,
    0x25d4, 0xae63, 0xb90d, 0x32ba, 0x97d1, 0x1c66, 0x0b08, 0x80bf, 0xca69, 0x41de, 0x56b0, 0xdd07, 0x786c, 0xf3db, 0xe4b5, 0x6f02,
    0x3ab1, 0xb106, 0xa668, 0x2ddf, 0x88b4, 0x0303, 0x146d, 0x9fda, 0xd50c, 0x5ebb, 0x49d5, 0xc262, 0x6709, 0xecbe, 0xfbd0, 0x7067,
    0x6e7c, 0xe5cb, 0xf2a5, 0x7912, 0xdc79, 0x57ce, 0x40a0, 0xcb17, 0x81c1, 0x0a76, 0x1d18, 0x96af, 0x33c4, 0xb873, 0xaf1d, 0x24aa,
    0x932b, 0x189c, 0x0ff2, 0x8445, 0x212e, 0xaa99, 0xbdf7, 0x3640, 0x7c96, 0xf721, 0xe04f, 0x6bf8, 0xce93, 0x4524, 0x524a, 0xd9fd,
    0xc7e6, 0x4c51, 0x5b3f, 0xd088, 0x75e3, 0xfe54, 0xe93a, 0x628d, 0x285b, 0xa3ec, 0xb482, 0x3f35, 0x9a5e, 0x11e9, 0x0687, 0x8d30,
    0xe232, 0x6985, 0x7eeb, 0xf55c, 0x5037, 0xdb80, 0xccee, 0x4759, 0x0d8f, 0x8638, 0x9156, 0x1ae1, 0xbf8a, 0x343d, 0x2353, 0xa8e4,
    0xb6ff, 0x3d48, 0x2a26, 0xa191, 0x04fa, 0x8f4d, 0x9823, 0x1394, 0x5942, 0xd2f5, 0xc59b, 0x4e2c, 0xeb47, 0x60f0, 0x779e, 0xfc29,
    0x4ba8, 0xc01f, 0xd771, 0x5cc6, 0xf9ad, 0x721a, 0x6574, 0xeec3, 0xa415, 0x2fa2, 0x38cc, 0xb37b, 0x1610, 0x9da7, 0x8ac9, 0x017e,
    0x1f65, 0x94d2, 0x83bc, 0x080b, 0xad60, 0x26d7, 0x31b9, 0xba0e, 0xf0d8, 0x7b6f, 0x6c01, 0xe7b6, 0x42dd, 0xc96a, 0xde04, 0x55b3,
};

uint16_t crc16_t10_dif_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16t10_dif_table[tmp & 0xff];
    }
    return crc; // crc
}
/******************************************************************************
 * name:    crc-16/teledisk     x16+x15+x13+x7+x4+x2+x+1
 * poly:    0xa097
 * init:    0x0000
 * refin:   false
 * refout:  false
 * xorout:  0x0000
 * note:
 *****************************************************************************/
const static uint16_t crc16teledisk_table[256] = {
    0x0000, 0xa097, 0xe1b9, 0x412e, 0x63e5, 0xc372, 0x825c, 0x22cb, 0xc7ca, 0x675d, 0x2673, 0x86e4, 0xa42f, 0x04b8, 0x4596, 0xe501,
    0x2f03, 0x8f94, 0xceba, 0x6e2d, 0x4ce6, 0xec71, 0xad5f, 0x0dc8, 0xe8c9, 0x485e, 0x0970, 0xa9e7, 0x8b2c, 0x2bbb, 0x6a95, 0xca02,
    0x5e06, 0xfe91, 0xbfbf, 0x1f28, 0x3de3, 0x9d74, 0xdc5a, 0x7ccd, 0x99cc, 0x395b, 0x7875, 0xd8e2, 0xfa29, 0x5abe, 0x1b90, 0xbb07,
    0x7105, 0xd192, 0x90bc, 0x302b, 0x12e0, 0xb277, 0xf359, 0x53ce, 0xb6cf, 0x1658, 0x5776, 0xf7e1, 0xd52a, 0x75bd, 0x3493, 0x9404,
    0xbc0c, 0x1c9b, 0x5db5, 0xfd22, 0xdfe9, 0x7f7e, 0x3e50, 0x9ec7, 0x7bc6, 0xdb51, 0x9a7f, 0x3ae8, 0x1823, 0xb8b4, 0xf99a, 0x590d,
    0x930f, 0x3398, 0x72b6, 0xd221, 0xf0ea, 0x507d, 0x1153, 0xb1c4, 0x54c5, 0xf452, 0xb57c, 0x15eb, 0x3720, 0x97b7, 0xd699, 0x760e,
    0xe20a, 0x429d, 0x03b3, 0xa324, 0x81ef, 0x2178, 0x6056, 0xc0c1, 0x25c0, 0x8557, 0xc479, 0x64ee, 0x4625, 0xe6b2, 0xa79c, 0x070b,
    0xcd09, 0x6d9e, 0x2cb0, 0x8c27, 0xaeec, 0x0e7b, 0x4f55, 0xefc2, 0x0ac3, 0xaa54, 0xeb7a, 0x4bed, 0x6926, 0xc9b1, 0x889f, 0x2808,
    0xd88f, 0x7818, 0x3936, 0x99a1, 0xbb6a, 0x1bfd, 0x5ad3, 0xfa44, 0x1f45, 0xbfd2, 0xfefc, 0x5e6b, 0x7ca0, 0xdc37, 0x9d19, 0x3d8e,
    0xf78c, 0x571b, 0x1635, 0xb6a2, 0x9469, 0x34fe, 0x75d0, 0xd547, 0x3046, 0x90d1, 0xd1ff, 0x7168, 0x53a3, 0xf334, 0xb21a, 0x128d,
    0x8689, 0x261e, 0x6730, 0xc7a7, 0xe56c, 0x45fb, 0x04d5, 0xa442, 0x4143, 0xe1d4, 0xa0fa, 0x006d, 0x22a6, 0x8231, 0xc31f, 0x6388,
    0xa98a, 0x091d, 0x4833, 0xe8a4, 0xca6f, 0x6af8, 0x2bd6, 0x8b41, 0x6e40, 0xced7, 0x8ff9, 0x2f6e, 0x0da5, 0xad32, 0xec1c, 0x4c8b,
    0x6483, 0xc414, 0x853a, 0x25ad, 0x0766, 0xa7f1, 0xe6df, 0x4648, 0xa349, 0x03de, 0x42f0, 0xe267, 0xc0ac, 0x603b, 0x2115, 0x8182,
    0x4b80, 0xeb17, 0xaa39, 0x0aae, 0x2865, 0x88f2, 0xc9dc, 0x694b, 0x8c4a, 0x2cdd, 0x6df3, 0xcd64, 0xefaf, 0x4f38, 0x0e16, 0xae81,
    0x3a85, 0x9a12, 0xdb3c, 0x7bab, 0x5960, 0xf9f7, 0xb8d9, 0x184e, 0xfd4f, 0x5dd8, 0x1cf6, 0xbc61, 0x9eaa, 0x3e3d, 0x7f13, 0xdf84,
    0x1586, 0xb511, 0xf43f, 0x54a8, 0x7663, 0xd6f4, 0x97da, 0x374d, 0xd24c, 0x72db, 0x33f5, 0x9362, 0xb1a9, 0x113e, 0x5010, 0xf087,
};

uint16_t crc16_teledisk_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 8) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc16teledisk_table[tmp & 0xff];
    }
    return crc; // crc
}
/******************************************************************************
 * name:    crc-16/tms37157          x16+x12+x5+1
 * poly:    0x1021
 * init:    0x89ec
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * note:
 *****************************************************************************/
uint16_t crc16_tms37157_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0x3791;                // initial value    // 0x3791 = reverse 0x89ec
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return crc; // crc
}
/******************************************************************************
 * name:    crc-16/a          x16+x12+x5+1
 * poly:    0x1021
 * init:    0xc6c6
 * refin:   true
 * refout:  true
 * xorout:  0x0000
 * note:
 *****************************************************************************/
uint16_t crc16_a_calc(uint8_t *data, uint32_t length)
{
    uint16_t tmp = 0;
    uint16_t crc = 0x6363;                // initial value    // 0x6363 = reverse 0xc6c6
    while (length--)
    {
        tmp = (0x00ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc16ccitt_table[tmp & 0xff];
    }
    return crc; // crc
}



/******************************************************************************
 * name:    crc-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * poly:    0x4c11db7
 * init:    0xfffffff
 * refin:   true
 * refout:  true
 * xorout:  0xfffffff
 * alias:   crc_32/adccp
 * use:     winrar,ect.
 *****************************************************************************/
const static uint32_t crc32_table[256] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};

uint32_t crc32_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (0x000000ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc32_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffffffff
}

/******************************************************************************
 * name:    crc-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * note:    d for直接计算
 *****************************************************************************/
uint32_t crc32_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint32_t crc = 0xffffffff;        // initial value
    while (length--)
    {
        crc ^= *data++;                // crc ^= *data; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 1)
                crc = (crc >> 1) ^ 0xedb88320;// 0xedb88320= reverse 0x04c11db7
            else
                crc = (crc >> 1);
        }
    }
    return ~crc;
}

/******************************************************************************
 * name:    crc-32/mpeg-2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * poly:    0x4c11db7
 * init:    0xfffffff
 * refin:   false
 * refout:  false
 * xorout:  0x0000000
 * note:
 *****************************************************************************/
const static uint32_t crc32mpeg_2_table[256] = {
    0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
    0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
    0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
    0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
    0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
    0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
    0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
    0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
    0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
    0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
    0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
    0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
    0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
    0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
    0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
    0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
    0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
    0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
    0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
    0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
    0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
    0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
    0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
    0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
    0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
    0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
    0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
    0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
    0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
    0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
    0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
    0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
};

uint32_t crc32_mpeg_2_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (crc >> 24) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc32mpeg_2_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-32/mpeg-2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * note:    d for直接计算
 *****************************************************************************/
uint32_t crc32_mpeg_2_d(uint8_t *data, uint32_t length)
{
    uint8_t i;
    uint32_t crc = 0xffffffff;  // initial value
    while (length--)
    {
        crc ^= (uint32_t)(*data++) << 24;// crc ^=(uint32_t)(*data)<<24; data++;
        for (i = 0; i < 8; ++i)
        {
            if (crc & 0x80000000)
                crc = (crc << 1) ^ 0x04c11db7;
            else
                crc <<= 1;
        }
    }
    return crc;
}


/******************************************************************************
 * name:    crc-32/bzip2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * poly:    0x4c11db7
 * init:    0xfffffff
 * refin:   false
 * refout:  false
 * xorout:  0xfffffff
 * note:
 *****************************************************************************/
uint32_t crc32_bzip2_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (crc >> 24) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc32mpeg_2_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffffffff
}
/******************************************************************************
 * name:    crc-32/posix  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * poly:    0x4c11db7
 * init:    0x0000000
 * refin:   false
 * refout:  false
 * xorout:  0xfffffff
 * note:
 *****************************************************************************/
uint32_t crc32_posix_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0x0000000;                // initial value
    while (length--)
    {
        tmp = (crc >> 24) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc32mpeg_2_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffffffff
}
/******************************************************************************
 * name:    crc-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
 * poly:    0x4c11db7
 * init:    0xfffffff
 * refin:   true
 * refout:  true
 * xorout:  0x0000000
 * alias:   crc_32/adccp
 * use:     winrar,ect.
 *****************************************************************************/
uint32_t crc32_jamcrc_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (0x000000ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc32_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-32/xfer  x32+x7+x5+x3+x3+x+1
 * poly:    0x000000af
 * init:    0x00000000
 * refin:   false
 * refout:  false
 * xorout:  0x00000000
 * note:
 *****************************************************************************/
const static uint32_t crc32xfer_table[256] = {
    0x00000000, 0x000000af, 0x0000015e, 0x000001f1, 0x000002bc, 0x00000213, 0x000003e2, 0x0000034d,
    0x00000578, 0x000005d7, 0x00000426, 0x00000489, 0x000007c4, 0x0000076b, 0x0000069a, 0x00000635,
    0x00000af0, 0x00000a5f, 0x00000bae, 0x00000b01, 0x0000084c, 0x000008e3, 0x00000912, 0x000009bd,
    0x00000f88, 0x00000f27, 0x00000ed6, 0x00000e79, 0x00000d34, 0x00000d9b, 0x00000c6a, 0x00000cc5,
    0x000015e0, 0x0000154f, 0x000014be, 0x00001411, 0x0000175c, 0x000017f3, 0x00001602, 0x000016ad,
    0x00001098, 0x00001037, 0x000011c6, 0x00001169, 0x00001224, 0x0000128b, 0x0000137a, 0x000013d5,
    0x00001f10, 0x00001fbf, 0x00001e4e, 0x00001ee1, 0x00001dac, 0x00001d03, 0x00001cf2, 0x00001c5d,
    0x00001a68, 0x00001ac7, 0x00001b36, 0x00001b99, 0x000018d4, 0x0000187b, 0x0000198a, 0x00001925,
    0x00002bc0, 0x00002b6f, 0x00002a9e, 0x00002a31, 0x0000297c, 0x000029d3, 0x00002822, 0x0000288d,
    0x00002eb8, 0x00002e17, 0x00002fe6, 0x00002f49, 0x00002c04, 0x00002cab, 0x00002d5a, 0x00002df5,
    0x00002130, 0x0000219f, 0x0000206e, 0x000020c1, 0x0000238c, 0x00002323, 0x000022d2, 0x0000227d,
    0x00002448, 0x000024e7, 0x00002516, 0x000025b9, 0x000026f4, 0x0000265b, 0x000027aa, 0x00002705,
    0x00003e20, 0x00003e8f, 0x00003f7e, 0x00003fd1, 0x00003c9c, 0x00003c33, 0x00003dc2, 0x00003d6d,
    0x00003b58, 0x00003bf7, 0x00003a06, 0x00003aa9, 0x000039e4, 0x0000394b, 0x000038ba, 0x00003815,
    0x000034d0, 0x0000347f, 0x0000358e, 0x00003521, 0x0000366c, 0x000036c3, 0x00003732, 0x0000379d,
    0x000031a8, 0x00003107, 0x000030f6, 0x00003059, 0x00003314, 0x000033bb, 0x0000324a, 0x000032e5,
    0x00005780, 0x0000572f, 0x000056de, 0x00005671, 0x0000553c, 0x00005593, 0x00005462, 0x000054cd,
    0x000052f8, 0x00005257, 0x000053a6, 0x00005309, 0x00005044, 0x000050eb, 0x0000511a, 0x000051b5,
    0x00005d70, 0x00005ddf, 0x00005c2e, 0x00005c81, 0x00005fcc, 0x00005f63, 0x00005e92, 0x00005e3d,
    0x00005808, 0x000058a7, 0x00005956, 0x000059f9, 0x00005ab4, 0x00005a1b, 0x00005bea, 0x00005b45,
    0x00004260, 0x000042cf, 0x0000433e, 0x00004391, 0x000040dc, 0x00004073, 0x00004182, 0x0000412d,
    0x00004718, 0x000047b7, 0x00004646, 0x000046e9, 0x000045a4, 0x0000450b, 0x000044fa, 0x00004455,
    0x00004890, 0x0000483f, 0x000049ce, 0x00004961, 0x00004a2c, 0x00004a83, 0x00004b72, 0x00004bdd,
    0x00004de8, 0x00004d47, 0x00004cb6, 0x00004c19, 0x00004f54, 0x00004ffb, 0x00004e0a, 0x00004ea5,
    0x00007c40, 0x00007cef, 0x00007d1e, 0x00007db1, 0x00007efc, 0x00007e53, 0x00007fa2, 0x00007f0d,
    0x00007938, 0x00007997, 0x00007866, 0x000078c9, 0x00007b84, 0x00007b2b, 0x00007ada, 0x00007a75,
    0x000076b0, 0x0000761f, 0x000077ee, 0x00007741, 0x0000740c, 0x000074a3, 0x00007552, 0x000075fd,
    0x000073c8, 0x00007367, 0x00007296, 0x00007239, 0x00007174, 0x000071db, 0x0000702a, 0x00007085,
    0x000069a0, 0x0000690f, 0x000068fe, 0x00006851, 0x00006b1c, 0x00006bb3, 0x00006a42, 0x00006aed,
    0x00006cd8, 0x00006c77, 0x00006d86, 0x00006d29, 0x00006e64, 0x00006ecb, 0x00006f3a, 0x00006f95,
    0x00006350, 0x000063ff, 0x0000620e, 0x000062a1, 0x000061ec, 0x00006143, 0x000060b2, 0x0000601d,
    0x00006628, 0x00006687, 0x00006776, 0x000067d9, 0x00006494, 0x0000643b, 0x000065ca, 0x00006565,
};

uint32_t crc32_xfer_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 24) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc32xfer_table[tmp & 0xff];
    }
    return crc; // crc
}

/******************************************************************************
 * name:    crc-32/c
 * poly:    0x1edc6f41
 * init:    0xfffffff
 * refin:   true
 * refout:  true
 * xorout:  0xfffffff
 *****************************************************************************/
const static uint32_t crc32c_table[256] = {
    0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
    0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
    0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
    0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
    0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
    0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
    0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
    0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
    0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
    0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
    0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
    0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
    0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
    0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
    0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
    0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
    0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
    0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
    0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
    0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
    0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
    0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
    0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
    0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
    0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
    0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
    0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
    0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
    0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
    0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
    0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
    0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
};

uint32_t crc32_c_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (0x000000ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc32c_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffffffff
}

/******************************************************************************
 * name:    crc-32/d
 * poly:    0xa833982b
 * init:    0xffffffff
 * refin:   true
 * refout:  true
 * xorout:  0xffffffff
 *****************************************************************************/
const static uint32_t crc32d_table[256] = {
    0x00000000, 0x2bddd04f, 0x57bba09e, 0x7c6670d1, 0xaf77413c, 0x84aa9173, 0xf8cce1a2, 0xd31131ed,
    0xf6dd1a53, 0xdd00ca1c, 0xa166bacd, 0x8abb6a82, 0x59aa5b6f, 0x72778b20, 0x0e11fbf1, 0x25cc2bbe,
    0x4589ac8d, 0x6e547cc2, 0x12320c13, 0x39efdc5c, 0xeafeedb1, 0xc1233dfe, 0xbd454d2f, 0x96989d60,
    0xb354b6de, 0x98896691, 0xe4ef1640, 0xcf32c60f, 0x1c23f7e2, 0x37fe27ad, 0x4b98577c, 0x60458733,
    0x8b13591a, 0xa0ce8955, 0xdca8f984, 0xf77529cb, 0x24641826, 0x0fb9c869, 0x73dfb8b8, 0x580268f7,
    0x7dce4349, 0x56139306, 0x2a75e3d7, 0x01a83398, 0xd2b90275, 0xf964d23a, 0x8502a2eb, 0xaedf72a4,
    0xce9af597, 0xe54725d8, 0x99215509, 0xb2fc8546, 0x61edb4ab, 0x4a3064e4, 0x36561435, 0x1d8bc47a,
    0x3847efc4, 0x139a3f8b, 0x6ffc4f5a, 0x44219f15, 0x9730aef8, 0xbced7eb7, 0xc08b0e66, 0xeb56de29,
    0xbe152a1f, 0x95c8fa50, 0xe9ae8a81, 0xc2735ace, 0x11626b23, 0x3abfbb6c, 0x46d9cbbd, 0x6d041bf2,
    0x48c8304c, 0x6315e003, 0x1f7390d2, 0x34ae409d, 0xe7bf7170, 0xcc62a13f, 0xb004d1ee, 0x9bd901a1,
    0xfb9c8692, 0xd04156dd, 0xac27260c, 0x87faf643, 0x54ebc7ae, 0x7f3617e1, 0x03506730, 0x288db77f,
    0x0d419cc1, 0x269c4c8e, 0x5afa3c5f, 0x7127ec10, 0xa236ddfd, 0x89eb0db2, 0xf58d7d63, 0xde50ad2c,
    0x35067305, 0x1edba34a, 0x62bdd39b, 0x496003d4, 0x9a713239, 0xb1ace276, 0xcdca92a7, 0xe61742e8,
    0xc3db6956, 0xe806b919, 0x9460c9c8, 0xbfbd1987, 0x6cac286a, 0x4771f825, 0x3b1788f4, 0x10ca58bb,
    0x708fdf88, 0x5b520fc7, 0x27347f16, 0x0ce9af59, 0xdff89eb4, 0xf4254efb, 0x88433e2a, 0xa39eee65,
    0x8652c5db, 0xad8f1594, 0xd1e96545, 0xfa34b50a, 0x292584e7, 0x02f854a8, 0x7e9e2479, 0x5543f436,
    0xd419cc15, 0xffc41c5a, 0x83a26c8b, 0xa87fbcc4, 0x7b6e8d29, 0x50b35d66, 0x2cd52db7, 0x0708fdf8,
    0x22c4d646, 0x09190609, 0x757f76d8, 0x5ea2a697, 0x8db3977a, 0xa66e4735, 0xda0837e4, 0xf1d5e7ab,
    0x91906098, 0xba4db0d7, 0xc62bc006, 0xedf61049, 0x3ee721a4, 0x153af1eb, 0x695c813a, 0x42815175,
    0x674d7acb, 0x4c90aa84, 0x30f6da55, 0x1b2b0a1a, 0xc83a3bf7, 0xe3e7ebb8, 0x9f819b69, 0xb45c4b26,
    0x5f0a950f, 0x74d74540, 0x08b13591, 0x236ce5de, 0xf07dd433, 0xdba0047c, 0xa7c674ad, 0x8c1ba4e2,
    0xa9d78f5c, 0x820a5f13, 0xfe6c2fc2, 0xd5b1ff8d, 0x06a0ce60, 0x2d7d1e2f, 0x511b6efe, 0x7ac6beb1,
    0x1a833982, 0x315ee9cd, 0x4d38991c, 0x66e54953, 0xb5f478be, 0x9e29a8f1, 0xe24fd820, 0xc992086f,
    0xec5e23d1, 0xc783f39e, 0xbbe5834f, 0x90385300, 0x432962ed, 0x68f4b2a2, 0x1492c273, 0x3f4f123c,
    0x6a0ce60a, 0x41d13645, 0x3db74694, 0x166a96db, 0xc57ba736, 0xeea67779, 0x92c007a8, 0xb91dd7e7,
    0x9cd1fc59, 0xb70c2c16, 0xcb6a5cc7, 0xe0b78c88, 0x33a6bd65, 0x187b6d2a, 0x641d1dfb, 0x4fc0cdb4,
    0x2f854a87, 0x04589ac8, 0x783eea19, 0x53e33a56, 0x80f20bbb, 0xab2fdbf4, 0xd749ab25, 0xfc947b6a,
    0xd95850d4, 0xf285809b, 0x8ee3f04a, 0xa53e2005, 0x762f11e8, 0x5df2c1a7, 0x2194b176, 0x0a496139,
    0xe11fbf10, 0xcac26f5f, 0xb6a41f8e, 0x9d79cfc1, 0x4e68fe2c, 0x65b52e63, 0x19d35eb2, 0x320e8efd,
    0x17c2a543, 0x3c1f750c, 0x407905dd, 0x6ba4d592, 0xb8b5e47f, 0x93683430, 0xef0e44e1, 0xc4d394ae,
    0xa496139d, 0x8f4bc3d2, 0xf32db303, 0xd8f0634c, 0x0be152a1, 0x203c82ee, 0x5c5af23f, 0x77872270,
    0x524b09ce, 0x7996d981, 0x05f0a950, 0x2e2d791f, 0xfd3c48f2, 0xd6e198bd, 0xaa87e86c, 0x815a3823,
};

uint32_t crc32_d_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0xffffffff;                // initial value
    while (length--)
    {
        tmp = (0x000000ff & crc) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc >> 8) ^ crc32d_table[tmp & 0xff];
    }
    return ~crc; // crc ^ 0xffffffff
}

/******************************************************************************
 * name:    crc-32/q
 * poly:    0x814141ab
 * init:    0x00000000
 * refin:   false
 * refout:  false
 * xorout:  0x00000000
 * note:
 *****************************************************************************/
const static uint32_t crc32q_table[256] = {
    0x00000000, 0x814141ab, 0x83c3c2fd, 0x02828356, 0x86c6c451, 0x078785fa, 0x050506ac, 0x84444707,
    0x8cccc909, 0x0d8d88a2, 0x0f0f0bf4, 0x8e4e4a5f, 0x0a0a0d58, 0x8b4b4cf3, 0x89c9cfa5, 0x08888e0e,
    0x98d8d3b9, 0x19999212, 0x1b1b1144, 0x9a5a50ef, 0x1e1e17e8, 0x9f5f5643, 0x9dddd515, 0x1c9c94be,
    0x14141ab0, 0x95555b1b, 0x97d7d84d, 0x169699e6, 0x92d2dee1, 0x13939f4a, 0x11111c1c, 0x90505db7,
    0xb0f0e6d9, 0x31b1a772, 0x33332424, 0xb272658f, 0x36362288, 0xb7776323, 0xb5f5e075, 0x34b4a1de,
    0x3c3c2fd0, 0xbd7d6e7b, 0xbfffed2d, 0x3ebeac86, 0xbafaeb81, 0x3bbbaa2a, 0x3939297c, 0xb87868d7,
    0x28283560, 0xa96974cb, 0xabebf79d, 0x2aaab636, 0xaeeef131, 0x2fafb09a, 0x2d2d33cc, 0xac6c7267,
    0xa4e4fc69, 0x25a5bdc2, 0x27273e94, 0xa6667f3f, 0x22223838, 0xa3637993, 0xa1e1fac5, 0x20a0bb6e,
    0xe0a08c19, 0x61e1cdb2, 0x63634ee4, 0xe2220f4f, 0x66664848, 0xe72709e3, 0xe5a58ab5, 0x64e4cb1e,
    0x6c6c4510, 0xed2d04bb, 0xefaf87ed, 0x6eeec646, 0xeaaa8141, 0x6bebc0ea, 0x696943bc, 0xe8280217,
    0x78785fa0, 0xf9391e0b, 0xfbbb9d5d, 0x7afadcf6, 0xfebe9bf1, 0x7fffda5a, 0x7d7d590c, 0xfc3c18a7,
    0xf4b496a9, 0x75f5d702, 0x77775454, 0xf63615ff, 0x727252f8, 0xf3331353, 0xf1b19005, 0x70f0d1ae,
    0x50506ac0, 0xd1112b6b, 0xd393a83d, 0x52d2e996, 0xd696ae91, 0x57d7ef3a, 0x55556c6c, 0xd4142dc7,
    0xdc9ca3c9, 0x5ddde262, 0x5f5f6134, 0xde1e209f, 0x5a5a6798, 0xdb1b2633, 0xd999a565, 0x58d8e4ce,
    0xc888b979, 0x49c9f8d2, 0x4b4b7b84, 0xca0a3a2f, 0x4e4e7d28, 0xcf0f3c83, 0xcd8dbfd5, 0x4cccfe7e,
    0x44447070, 0xc50531db, 0xc787b28d, 0x46c6f326, 0xc282b421, 0x43c3f58a, 0x414176dc, 0xc0003777,
    0x40005999, 0xc1411832, 0xc3c39b64, 0x4282dacf, 0xc6c69dc8, 0x4787dc63, 0x45055f35, 0xc4441e9e,
    0xcccc9090, 0x4d8dd13b, 0x4f0f526d, 0xce4e13c6, 0x4a0a54c1, 0xcb4b156a, 0xc9c9963c, 0x4888d797,
    0xd8d88a20, 0x5999cb8b, 0x5b1b48dd, 0xda5a0976, 0x5e1e4e71, 0xdf5f0fda, 0xdddd8c8c, 0x5c9ccd27,
    0x54144329, 0xd5550282, 0xd7d781d4, 0x5696c07f, 0xd2d28778, 0x5393c6d3, 0x51114585, 0xd050042e,
    0xf0f0bf40, 0x71b1feeb, 0x73337dbd, 0xf2723c16, 0x76367b11, 0xf7773aba, 0xf5f5b9ec, 0x74b4f847,
    0x7c3c7649, 0xfd7d37e2, 0xffffb4b4, 0x7ebef51f, 0xfafab218, 0x7bbbf3b3, 0x793970e5, 0xf878314e,
    0x68286cf9, 0xe9692d52, 0xebebae04, 0x6aaaefaf, 0xeeeea8a8, 0x6fafe903, 0x6d2d6a55, 0xec6c2bfe,
    0xe4e4a5f0, 0x65a5e45b, 0x6727670d, 0xe66626a6, 0x622261a1, 0xe363200a, 0xe1e1a35c, 0x60a0e2f7,
    0xa0a0d580, 0x21e1942b, 0x2363177d, 0xa22256d6, 0x266611d1, 0xa727507a, 0xa5a5d32c, 0x24e49287,
    0x2c6c1c89, 0xad2d5d22, 0xafafde74, 0x2eee9fdf, 0xaaaad8d8, 0x2beb9973, 0x29691a25, 0xa8285b8e,
    0x38780639, 0xb9394792, 0xbbbbc4c4, 0x3afa856f, 0xbebec268, 0x3fff83c3, 0x3d7d0095, 0xbc3c413e,
    0xb4b4cf30, 0x35f58e9b, 0x37770dcd, 0xb6364c66, 0x32720b61, 0xb3334aca, 0xb1b1c99c, 0x30f08837,
    0x10503359, 0x911172f2, 0x9393f1a4, 0x12d2b00f, 0x9696f708, 0x17d7b6a3, 0x155535f5, 0x9414745e,
    0x9c9cfa50, 0x1dddbbfb, 0x1f5f38ad, 0x9e1e7906, 0x1a5a3e01, 0x9b1b7faa, 0x9999fcfc, 0x18d8bd57,
    0x8888e0e0, 0x09c9a14b, 0x0b4b221d, 0x8a0a63b6, 0x0e4e24b1, 0x8f0f651a, 0x8d8de64c, 0x0ccca7e7,
    0x044429e9, 0x85056842, 0x8787eb14, 0x06c6aabf, 0x8282edb8, 0x03c3ac13, 0x01412f45, 0x80006eee,
};

uint32_t crc32_q_calc(uint8_t *data, uint32_t length)
{
    uint32_t tmp = 0;
    uint32_t crc = 0;                // initial value
    while (length--)
    {
        tmp = (crc >> 24) ^ (*data++);    // crc ^= *data; data++;
        crc = (crc << 8) ^ crc32q_table[tmp & 0xff];
    }
    return crc; // crc
}


